using System;
using System.IO;
using System.Xml;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Security.Principal;
using System.Reflection;
using System.Threading;
using System.Runtime.InteropServices;
using System.Net;
using System.Diagnostics;

using Microsoft.Crm.Sdk.Proxy;
using Microsoft.Crm.Sdk.Discovery.Proxy;
using Microsoft.Crm.Sdk.Helpers;
using Microsoft.Crm.Passport.IdCrl;

namespace dbPopulator
{
	public class FileWriter
	{
		private static FileWriter m_instance;
		private StreamWriter m_errorWriter;
		private TextWriter writer;
		private static string startTime;
		private FileStream fs;

		public static FileWriter Instance
		{
			get
			{
				return m_instance;
			}
		}

		public static string StartTime
		{
			get
			{
				return startTime;
			}
		}

		static FileWriter()
		{
			m_instance = new FileWriter();
		}

		public void CreateFileWriter(string fileName)
		{
            string name = fileName.Substring(0,fileName.IndexOf('.'));
			fs = File.Open(name + "_Errors_"+startTime+".txt",FileMode.Create,FileAccess.Write,FileShare.ReadWrite);
			m_errorWriter = new StreamWriter(fs);
			m_errorWriter.AutoFlush = true;
			writer = StreamWriter.Synchronized(m_errorWriter);
		}

		public FileWriter()
		{			
			startTime = System.DateTime.Now.ToString("dd-MM-yy") + "-" + System.DateTime.Now.Ticks.ToString();		
		}

		public void Close()
		{
			writer.Close();
			m_errorWriter.Close();
			fs.Close();
		}

		//
		// Error writing function to write to error file.
		//
		[System.Runtime.CompilerServices.MethodImpl (System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
		public void WriteToFile(string output)
		{
			if(false == System.Threading.Monitor.TryEnter(m_instance))
			{
				System.Threading.Monitor.Enter(m_instance);
			}
			try
			{					
				writer.WriteLine(output);		
				writer.Flush();				
			}
			finally
			{
				System.Threading.Monitor.Exit(m_instance);
			}			
		}
	}

	/// <summary>
	/// Summary description for Class1.	/// </summary>
	public class DbPopulator
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		
		/// <summary>
		/// Name of the xml config file
		/// </summary>
		private string m_xmlFile;
		
		/// <summary>
		/// Cache of usernames
		/// </summary>
		private ArrayList m_userNames;

		/// <summary>
		/// Cache of passwords
		/// </summary>
		private ArrayList m_userPasswords;

        /// <summary>
        /// Cache of OrganizationNames
        /// </summary>
        private ArrayList m_OrganizationNames;

		/// <summary>
		/// Name of the domain
		/// </summary>
		private string m_domain;

		/// <summary>
		/// Name of the Server
		/// </summary>
		private string m_webServer;

        /// <summary>
        /// Name used with passport server for partner name
        /// </summary>
        private string m_partner;

        /// <summary>
        /// Name of server which is running the discovery service.
        /// If omitted then we should default to webserver name
        /// </summary>
        private string m_discoveryServer;

        /// <summary>
        /// Name of organization
        /// </summary>
        private string m_organizationName;

        /// <summary>
        /// Organization Id
        /// </summary>
        private Guid m_organizationId;
        
		/// <summary>
		/// Url holding the Unified SDK web service
		/// </summary>
		private string m_webServerUrl;

        /// <summary>
        /// Boolean value specifying if calls to webservices are SSL or not
        /// </summary>
        private bool m_ssl;

		/// <summary>
		/// Placeholder that stores index of the current user to populate the entities
		/// </summary>
		private int m_currentIdx;

        /// <summary>
        /// Placeholder for having a single counter for uniqueness
        /// </summary>
        private static int m_currentCounter;

		/// <summary>
		/// XmlDocument read from the configuration file
		/// </summary>
		private XmlDocument m_xmlDocument;

		/// <summary>
		/// Root node of the xml document.
		/// </summary>
		private XmlNode m_root;

		/// <summary>
		/// Number of threads being run
		/// </summary>
		private int m_numberOfThreads;

        /// <summary>
        /// User name base
        /// </summary>
        private string m_usernameBase;

        /// <summary>
        /// Password
        /// </summary>
        private string m_password;

        /// <summary>
        /// String specifying if the Authentication scheme
        /// </summary>
        private string m_authentication;

        private int m_startIdx;

        private int m_count;

        /// <summary>
        /// serviceid for getting passport ticket
        /// </summary>
        private readonly Guid m_serviceId = new Guid("{DF60E2DF-88AD-4526-AE21-83D130EF0FA8}");


        public XmlNode Root
        {
            get
            {
                return m_root;
            }
        }

        public Guid ServiceId
        {
            get
            {
                return m_serviceId;
            }
        }

        public bool SSL
        {
            get
            {
                return m_ssl;
            }
        }

        /// <summary>
        /// The passport environment for now is INT
        /// </summary>
        private string PassportEnvironment = "INT";

        /// <summary>
        /// The domain name of the passport.
        /// Eg: hotmail-int, hotmail, etc.
        /// </summary>
        private string m_passportDomain;

        public string PassportDomain
        {
            get
            {
                return m_passportDomain;
            }
        }

        public string Partner
        {
            get
            {
                return m_partner;
            }
        }

        public string DiscoveryServer
        {
            get
            {
                return m_discoveryServer;
            }
        }

		

		/// <summary>
		/// List of entityTemplates
		/// </summary>
		private ArrayList m_entityTemplateList;

		/// <summary>
		/// Quiet Mode
		/// </summary>
		private bool m_quietMode;

        /// <summary>
        /// Config File Name
        /// </summary>
        private string m_configFileName;

		public bool QuietMode
		{
			get
			{
				return m_quietMode;
			}
			set
			{
				m_quietMode = value;
			}
		}        

        public string AuthenticationScheme
        {
            get
            {
                return m_authentication;
            }
        }       

		public DbPopulator(string [] args)
		{
            m_xmlDocument = new XmlDocument();
			m_root = null;
			m_entityTemplateList = new ArrayList();
			m_userNames = new ArrayList();
			m_userPasswords = new ArrayList();
            m_OrganizationNames = new ArrayList();
			m_currentIdx = 0;
            m_currentCounter = 1;
			m_domain = "";
			m_webServer = "";
            m_organizationName = "";
            m_usernameBase = "";
            m_password = "";
            m_startIdx = -1;
            m_count = -1;
            m_authentication = "AD";
            m_passportDomain = "";
            m_partner = "";
            m_discoveryServer = "";
            m_ssl = false;            

			//Default information
			m_numberOfThreads = -1;
			m_webServerUrl = "http://localhost/MSCRMServices/2007/CRMService.asmx";
                       

            if (args.Length > 0)
            {
                m_configFileName = args[0];
                FileWriter.Instance.CreateFileWriter(m_configFileName);
            }

            for (int i = 1; i < args.Length; i++)
            {
                if (args[i].ToLower().Equals("-q"))
                {
                    m_quietMode = true;
                }
                else if (args[i].ToLower().Contains("/domain:"))
                {
                    m_domain = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/webserver:"))
                {
                    m_webServer = args[i].Substring(args[i].IndexOf(':') + 1);
                    m_webServerUrl = m_webServerUrl.Replace("localhost", m_webServer);
                }
                else if (args[i].ToLower().Contains("/threadcount:"))
                {
                    m_numberOfThreads = int.Parse(args[i].Substring(args[i].IndexOf(':') + 1));
                }
                else if (args[i].ToLower().Contains("/usernamebase:"))
                {
                    m_usernameBase = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/password:"))
                {
                    m_password = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/startidx:"))
                {
                    m_startIdx = int.Parse(args[i].Substring(args[i].IndexOf(':') + 1));
                }
                else if (args[i].ToLower().Contains("/count:"))
                {
                    m_count = int.Parse(args[i].Substring(args[i].IndexOf(':') + 1));
                }
                else if (args[i].ToLower().Contains("/orgname:"))
                {
                    m_organizationName = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/authentication:"))
                {
                    m_authentication = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/passportdomain:"))
                {
                    m_passportDomain = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/passportenvironment:"))
                {
                    PassportEnvironment = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/partner:"))
                {
                    m_partner = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if (args[i].ToLower().Contains("/discoveryserver:"))
                {
                    m_discoveryServer = args[i].Substring(args[i].IndexOf(':') + 1);
                }
                else if(args[i].ToLower().Contains("/ssl:"))
                {
                    m_ssl = bool.Parse(args[i].Substring(args[i].IndexOf(':') + 1));
                    if (m_ssl)
                    {
                        m_webServerUrl = m_webServerUrl.Replace("http://", "https://");
                    }
                }
            }
		}
                
		public ArrayList UserNames
		{
			get
			{
				return m_userNames;
			}
		}

		public ArrayList Passwords
		{
			get
			{
				return m_userPasswords;
			}
		}

        public ArrayList OrganizationNames
        {
            get
            {
                return m_OrganizationNames;
            }
        }

		public int GetCurrentIdx()
		{
			if(m_currentIdx == m_userNames.Count)
				return -1;
			else
				return m_currentIdx++;
		}

        public int GetCurrentCounter()
        {
            return m_currentCounter++;
        }

		public string Domain
		{
			get
			{
				return m_domain;
			}
		}        

        public Guid OrganizationId
        {
            get
            {
                return m_organizationId;
            }
        }

		public string WebServiceUrl
		{
			get
			{
				return m_webServerUrl;
			}
		}

        public string WebServer
        {
            get
            {
                return m_webServer;
            }
        }

		public ArrayList EntityTemplateList
		{
			get
			{
				return m_entityTemplateList;
			}
		}

		[STAThread]
		static void Main(string[] args)
		{
            DbPopulator dbPopulator;

            if (args.Length == 0 || args[0] == "/?" || args[0] == "-help")
            {
                Console.WriteLine("No xml file specified. Specify xml file as argument");
                Console.WriteLine("If domain and user specification are to be given through ");
                Console.WriteLine("command prompt arguments they can be specified as follows (if given through command prompt, the specs in config.xml will be overridden):");
                Console.WriteLine("dbPopulator.exe configFile.xml /domain:[domainName] /webserver:[webserver] /orgname:[organization name] /threadcount:[numberThreads] /usernamebase:[basename] /password:[password] /startidx:[start] /count:[numUsers] /authentication:[AD/passport] /partner:[Site name registered with Passport] /passportenvironment:[Eg:INT] /discoveryserver:[Machine where discovery service is running] /ssl:[true or false]");
                return;
            }
            			
			dbPopulator = new DbPopulator(args);
			
			//
			// Check if PerfMon Counters are set for the machine. If they are not set, then create the counters
			//
			dbPopulator.CheckPerfMonCounters();
            
			int dbRnTime = System.Environment.TickCount;
			dbPopulator.Start(args[0]);
			Console.WriteLine("\n dbpop Runtime is {0} ms", 
				System.Environment.TickCount-dbRnTime);

			FileWriter.Instance.Close();
		}

        public CrmDiscoveryService CreateDiscoveryService(string authentication)
        {
            CrmDiscoveryService service = new CrmDiscoveryService();
            string targetHostName;
            if (m_webServer == "")
            {
                targetHostName = "http://localhost";
            }
            else
            {
                targetHostName = "http://" + m_discoveryServer;
            }

            service.Url = string.Format("{0}/MSCRMServices/2007/{1}/CrmDiscoveryService.asmx", targetHostName, authentication);

            if (m_ssl)
            {
                service.Url = service.Url.Replace("http://", "https://");
            }

            return service;
        }

        public string GetPassportTicket(string policy, string userName, string password, string passportSiteDomain)
        {
            using (LogonManager lm = new LogonManager())
            {
                try
                {
                    string ticket = lm.Logon(ServiceId,
                        userName,
                        password,
                        passportSiteDomain,
                        policy, PassportEnvironment);                                       

                    return ticket;
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile("IDCRL Exception: " + e.ToString());
                    throw (e);
                }
            }
        }        

        public string RetrievePolicy()
        {
            CrmDiscoveryService service = CreateDiscoveryService(m_authentication);            

            RetrievePolicyRequest policyRequest = new RetrievePolicyRequest();

            RetrievePolicyResponse policyResponse = (RetrievePolicyResponse)service.Execute(policyRequest);

            return policyResponse.Policy;
        }

		public void CheckPerfMonCounters ()
		{
			PerformanceCounterType nmOfIt64 = PerformanceCounterType.NumberOfItems64;

            //PerformanceCounterCategory.Delete("CrmPrfCntrs");

            if (!PerformanceCounterCategory.Exists("CrmPrfCntrs"))
            {

                // Add the counter.
                CounterCreationData[] cntAry = new CounterCreationData[28];

                cntAry[0] = new CounterCreationData("accountCrtTm",
                    "Current Account creation Time", nmOfIt64);

                cntAry[1] = new CounterCreationData("annotationCrtTm",
                    "Current Annotation creation Time", nmOfIt64);

                cntAry[2] = new CounterCreationData("appointmentCrtTm",
                    "Current Appointment creation Time", nmOfIt64);

                cntAry[3] = new CounterCreationData("contactCrtTm",
                    "Current Contact creation Time", nmOfIt64);

                cntAry[4] = new CounterCreationData("customeraddressCrtTm",
                    "Current CustomerAddress creation Time", nmOfIt64);

                cntAry[5] = new CounterCreationData("discountCrtTm",
                    "Current Discount creation Time", nmOfIt64);

                cntAry[6] = new CounterCreationData("discounttypeCrtTm",
                    "Current DiscountType creation Time", nmOfIt64);

                cntAry[7] = new CounterCreationData("emailCrtTm",
                    "Current Email creation Time", nmOfIt64);

                cntAry[8] = new CounterCreationData("faxCrtTm",
                    "Current Fax creation Time", nmOfIt64);

                cntAry[9] = new CounterCreationData("incidentCrtTm",
                    "Current Case creation Time", nmOfIt64);

                cntAry[10] = new CounterCreationData("invoiceCrtTm",
                    "Current Invoice creation Time", nmOfIt64);

                cntAry[11] = new CounterCreationData("invoicedetailCrtTm",
                    "Current invoiceDetail creation Time", nmOfIt64);

                cntAry[12] = new CounterCreationData("leadCrtTm",
                    "Current Lead creation Time", nmOfIt64);

                cntAry[13] = new CounterCreationData("letterCrtTm",
                    "Current Letter creation Time", nmOfIt64);

                cntAry[14] = new CounterCreationData("opportunityCrtTm",
                    "Current Opportunity creation Time", nmOfIt64);

                cntAry[15] = new CounterCreationData("opportunityproductCrtTm",
                    "Current OpportunityProduct creation Time", nmOfIt64);

                cntAry[16] = new CounterCreationData("phonecallCrtTm",
                    "Current PhoneCall creation Time", nmOfIt64);

                cntAry[17] = new CounterCreationData("pricelevelCrtTm",
                    "Current Pricelevel creation Time", nmOfIt64);

                cntAry[18] = new CounterCreationData("productCrtTm",
                    "Current Product creation Time", nmOfIt64);

                cntAry[19] = new CounterCreationData("productpricelevelCrtTm",
                    "Current ProductPricelevel creation Time", nmOfIt64);

                cntAry[20] = new CounterCreationData("quoteCrtTm",
                    "Current Quote creation Time", nmOfIt64);

                cntAry[21] = new CounterCreationData("salesorderdetailCrtTm",
                    "Current SalesOrderDetail creation Time", nmOfIt64);

                cntAry[22] = new CounterCreationData("salesorderCrtTm",
                    "Current SalesOrder creation Time", nmOfIt64);

                cntAry[23] = new CounterCreationData("subjectCrtTm",
                    "Current Subject creation Time", nmOfIt64);

                cntAry[24] = new CounterCreationData("taskCrtTm",
                    "Current Task creation Time", nmOfIt64);

                cntAry[25] = new CounterCreationData("uomCrtTm",
                    "Current UoM creation Time", nmOfIt64);

                cntAry[26] = new CounterCreationData("uomscheduleCrtTm",
                    "Current UoMSchedule creation Time", nmOfIt64);

                cntAry[27] = new CounterCreationData("EntityCrtTm",
                    "Current Entity creation Time", nmOfIt64);


                // Add counter to group
                CounterCreationDataCollection CCDC = new CounterCreationDataCollection();
                CCDC.AddRange(cntAry);

                // Create the category.
                PerformanceCounterCategory.Create("CrmPrfCntrs", "Crm dbpop usage counters", PerformanceCounterCategoryType.SingleInstance,
                    CCDC);
            }
		}

		//
		// Start Point of the main class
		//
		public void Start (string configFile)
		{
			m_xmlFile = configFile;
			ReadFile();
			Initialize();
			
			XmlNode objectDist = m_root.SelectSingleNode("objectDist");
			CreateEntityTemplates(objectDist.ChildNodes, m_entityTemplateList);
            
			FireThreads ();
		}

		public void ReadFile()
		{
			try
			{
				m_xmlDocument.Load(m_xmlFile);
			}
			catch (XmlException e)
			{
				FileWriter.Instance.WriteToFile(string.Format("{0}\r\n{1}", "Xml Load Error:", e.Message));
			}
		}

		public void Initialize ()
		{
			try
			{
				m_root = m_xmlDocument.DocumentElement;
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
				Console.WriteLine(e.InnerException.Message);
				return;
			}
			XmlNode exec = m_root.SelectSingleNode("exec");
			if( exec != null)
			{
				try
				{
                    if (m_numberOfThreads == -1)
                    {
                        if (exec.Attributes["threadCount"] != null)
                        {
                            m_numberOfThreads = int.Parse(exec.Attributes["threadCount"].Value);
                        }
                        else
                        {
                            m_numberOfThreads = 10;
                        }
                    }
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Invalid input for threadCount, default number of 10 used");
				}
			}

            // Read if it is Live (Passport authentication) or Domain authentication
            ReadAuthentication();
			if(!CreateUsers())
				Console.WriteLine("Adding UserNames to cache failed");
			ReadDomainName();
            ReadServerName();
            ReadSSL();
            ReadOrgName();
            ReadDiscoveryServerName();
            ReadPartnerName();
            ReadPassportEnvironment();
            RetrieveOrgNames();
            RetrieveOrgId();
            
		}

		public bool CreateUsers()
		{
            string userNameBase = m_usernameBase;
            string userName = null;
            string password = m_password;
			int from = m_startIdx;
			int userCount = m_count;

            //
            // If m_usernameBase is entered from command prompt then userGroups will not be parsed
            // You can't have username base entered from command prompt and password read in from xmlconfig
            //
            if(m_usernameBase != "")
            {                
                if (m_startIdx >= 0)
                {
                    for (int j = 0; j < m_count; j++)
                    {
                        int append = (from + j);
                        userName = userNameBase + append.ToString();
                        m_userNames.Add(userName);
                        m_userPasswords.Add(password);
                    }
                }
                else
                {
                    // From and count don't exist. Just add the name to userNamesCache
                    m_userNames.Add(userNameBase);
                    m_userPasswords.Add(password);
                }
                return true;
            }

			XmlNode userGroups = m_root.SelectSingleNode("userGroups");
			XmlNodeList userGroupList = userGroups.SelectNodes("userGroup");
			
			if(userGroupList == null)
				return false;
			
			for(int i = 0; i < userGroupList.Count; i++)
			{
				XmlNode userGroup = userGroupList[i];
				try
				{
                    userNameBase = userGroup.Attributes["name"].Value;                 
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Invalid input for name");
				}

				try
				{                    
                    if (m_startIdx < 0 && userGroup.Attributes["startidx"] != null)
                        from = int.Parse(userGroup.Attributes["startidx"].Value);                 
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Invalid input of startidx, must be a number");
				}

				try
				{                    
                    if (m_count < 0 && userGroup.Attributes["count"] != null)
                        userCount = int.Parse(userGroup.Attributes["count"].Value);
                }
				catch
				{
					FileWriter.Instance.WriteToFile("Invalid input of userCount, must be a number");
				}

				try
				{
                    if (m_password == "")
                    {
                        password = userGroup.Attributes["password"].Value;
                    }
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Invalid input of password");
				}
				
				if(userNameBase != null)
				{
					if(from  >= 0)
					{
						for(int j = 0; j < userCount; j++)
						{
							int append = (from + j);
							userName = userNameBase + append.ToString();
                           
                            userName = AddPassportDomain(userName, userGroup);
							
                            m_userNames.Add(userName);
							m_userPasswords.Add(password);
						}
					}
					else
					{
						// From and count don't exist. Just add the name to userNamesCache
                        userNameBase = AddPassportDomain(userNameBase, userGroup);

						m_userNames.Add(userNameBase);
						m_userPasswords.Add(password);
					}
				}
				else
				{
					// no usernamebase
					if(from >= 0)
					{
						for(int j = 0; j < userCount; j++)
						{
							int userNumber = from + j;

                            string name = AddPassportDomain(userNumber.ToString(), userGroup);
							m_userNames.Add(name);
							m_userPasswords.Add(password);
						}
					}
				}
                
			}


            
			return true;
		}

        public string AddPassportDomain(string name, XmlNode userGroup)
        {
            if(m_authentication.ToLower().Equals("passport"))
            {
                if (m_passportDomain != "")
                {                        
                    name = name + "@" + m_passportDomain;                        
                }
                else
                {
                    try
                    {
                        if (userGroup.Attributes["passportdomain"] != null)
                        {
                            m_passportDomain = userGroup.Attributes["passportdomain"].Value;                            
                            name = name + "@" + m_passportDomain;
                        }
                        else
                        {
                            FileWriter.Instance.WriteToFile("Warning: Passportdomain is missing. If specified in username completely, then passportdomain is not necessary");
                        }
                    }
                    catch
                    {
                        FileWriter.Instance.WriteToFile("passport domain name is in wrong format");
                    }
                }
            }
            return name;
        }

		public void ReadDomainName()
		{
            if (m_domain != "")
                return;

			XmlNode userGroups = m_root.SelectSingleNode("userGroups");
			if(userGroups != null)
			{
				try
				{
					m_domain = userGroups.Attributes["domain"].Value;
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Domain name is wrong format");
				}
			}
		}
		public void ReadServerName()
		{
            if (m_webServer != "")
                return;

			XmlNode userGroups = m_root.SelectSingleNode("userGroups");
			if(userGroups != null)
			{
				try
				{
					if(userGroups.Attributes["webserver"].Value != null)
					{
						m_webServer = userGroups.Attributes["webserver"].Value;
						m_webServerUrl = "http://" + m_webServer + "/MSCRMServices/2007/CrmService.asmx";
					}
				}
				catch
				{
					FileWriter.Instance.WriteToFile("server name is wrong format");
				}
			}
			
		}

        public void ReadSSL()
        {
            if (m_ssl != false)
                return;

            XmlNode userGroups = m_root.SelectSingleNode("userGroups");
            if (userGroups != null)
            {
                try
                {
                    if (userGroups.Attributes["ssl"] != null)
                    {
                        m_ssl = bool.Parse(userGroups.Attributes["ssl"].Value);
                        if (m_ssl)
                        {
                            m_webServerUrl = m_webServerUrl.Replace("http://", "https://");
                        }
                    }
                }
                catch
                {
                    FileWriter.Instance.WriteToFile("ssl needs to be true or false, wrong format specified");
                }
            }

        }

        public void ReadOrgName()
        {
            if (m_organizationName != "")
                return;

            XmlNode userGroups = m_root.SelectSingleNode("userGroups");
            if (userGroups != null)
            {
                try
                {
                    if (userGroups.Attributes["organization"] != null)
                    {
                        m_organizationName = userGroups.Attributes["organization"].Value;
                    }
                    else
                    {
                        FileWriter.Instance.WriteToFile("Warning: Organization name is missing. If user belongs to single organization, the organization name can be retrieved but if user belongs to multiple orgs then organization name is required to determine which org to populate data for and dbPopulator will error out.");
                    }
                }
                catch
                {
                    FileWriter.Instance.WriteToFile("Organization name is in wrong format");
                }
            }
        }

        public void ReadDiscoveryServerName()
        {
            if (m_discoveryServer != "")
                return;

            XmlNode userGroups = m_root.SelectSingleNode("userGroups");
            if (userGroups != null)
            {
                try
                {
                    if (userGroups.Attributes["discoveryserver"] != null)
                    {
                        m_discoveryServer = userGroups.Attributes["discoveryserver"].Value;
                    }
                    else
                    {
                        m_discoveryServer = m_webServer;
                        FileWriter.Instance.WriteToFile("Discovery server name is missing, defaulting discoveryserver to webserver");
                    }
                }
                catch
                {
                    FileWriter.Instance.WriteToFile("server name is wrong format");
                }
            }

        }

        public void ReadPartnerName()
        {
            if (m_partner != "")
                return;

            XmlNode userGroups = m_root.SelectSingleNode("userGroups");
            if (userGroups != null)
            {
                try
                {
                    if (userGroups.Attributes["partner"] != null)
                    {
                        m_partner = userGroups.Attributes["partner"].Value;
                    }
                    else
                    {
                        m_partner = m_webServer;
                        FileWriter.Instance.WriteToFile("Partner name is missing, defaulting partner to webserver");
                    }
                }
                catch
                {
                    FileWriter.Instance.WriteToFile("partner name is wrong format");
                }
            }

        }

        public void ReadPassportEnvironment()
        {
            if (PassportEnvironment != "INT")
                return;

            XmlNode userGroups = m_root.SelectSingleNode("userGroups");
            if (userGroups != null)
            {
                try
                {
                    if (userGroups.Attributes["passportenvirontment"] != null)
                    {
                        PassportEnvironment = userGroups.Attributes["passportenvironment"].Value;
                    }
                }
                catch
                {
                    FileWriter.Instance.WriteToFile("passportenvironment name is wrong format");
                }
            }

        }

        public void RetrieveOrgNames()
        {
            for (int j = 0; j < m_userNames.Count; j++)
            {
                if (m_authentication.ToLower().Equals("passport") == true)
                {
                    CrmDiscoveryService discService = CreateDiscoveryService(m_authentication);

                    RetrieveOrganizationsRequest orgReq = new RetrieveOrganizationsRequest();
                    try
                    {
                        orgReq.PassportTicket = GetPassportTicket(RetrievePolicy(), (string)m_userNames[j], (string)m_userPasswords[j], m_partner);
                    }
                    catch (Exception e)
                    {
                        FileWriter.Instance.WriteToFile("Exception from GetPassportTicket:" + e.ToString());
                        Environment.Exit(1);
                    }

                    RetrieveOrganizationsResponse orgResp;
                    try
                    {
                        orgResp = (RetrieveOrganizationsResponse)discService.Execute(orgReq);
                        OrganizationDetail[] orgDetailList = orgResp.OrganizationDetails;


                        if (orgDetailList.Length == 0)
                        {
                            if (m_organizationName != "")
                            {
                                m_OrganizationNames.Add(m_organizationName);
                            }
                            else
                            {
                                throw new Exception("OrgDetails had a length of Zero, Unexpected.");
                            }
                        }
                        else if (orgDetailList.Length > 1)
                        {
                            // For administrator who provisions multiple organizations
                            // we need to know which organization to populate for
                            if (m_organizationName != "")
                            {
                                m_OrganizationNames.Add(m_organizationName);
                            }
                            else
                            {
                                // if no organization name is specified in xml or arguments list
                                // take the first organization name from list.
                                m_OrganizationNames.Add(orgDetailList[0].OrganizationName);
                            }
                        }
                        else
                        {
                            // if only one organization is found then take it.
                            m_OrganizationNames.Add(orgDetailList[0].OrganizationName);
                        }
                    }
                    catch (Exception e)
                    {
                        FileWriter.Instance.WriteToFile("Exception when retrieving OrgDetails:" + e.ToString());
                        Environment.Exit(1);
                    }
                }
                else if (m_authentication.ToLower().Equals("ad") == true)
                {                    
                    CrmDiscoveryService discService = CreateDiscoveryService(m_authentication);

                    NetworkCredential creds = new NetworkCredential((string)m_userNames[j], (string)m_userPasswords[j], m_domain);
                    discService.Credentials = creds;

                    RetrieveOrganizationsRequest orgReq = new RetrieveOrganizationsRequest();
                    try
                    {
                        orgReq.UserId = m_domain + "\\" + (string)m_userNames[j];
                        orgReq.Password = (string)m_userPasswords[j];
                    }
                    catch (Exception e)
                    {
                        FileWriter.Instance.WriteToFile("Exception when adding UserId and Pwd to orgRequest:" + e.ToString());
                    }

                    RetrieveOrganizationsResponse orgResp;
                    try
                    {
                        orgResp = (RetrieveOrganizationsResponse)discService.Execute(orgReq);
                        OrganizationDetail[] orgDetailList = orgResp.OrganizationDetails;

                        if (orgDetailList.Length == 0)
                        {
                            if (m_organizationName != "")
                            {
                                m_OrganizationNames.Add(m_organizationName);
                            }
                            else
                            {
                                throw new Exception("OrgDetails had a length of Zero, Unexpected.");
                            }
                        }
                        else if (orgDetailList.Length > 1)
                        {
                            // For administrator who provisions multiple organizations
                            // we need to know which organization to populate for
                            if (m_organizationName != "")
                            {
                                m_OrganizationNames.Add(m_organizationName);
                            }
                            else
                            {
                                // if no organization name is specified in xml or arguments list
                                // take the first organization name from list.
                                m_OrganizationNames.Add(orgDetailList[0].OrganizationName);
                            }
                        }
                        else
                        {
                            // if only one organization is found then take it.
                            m_OrganizationNames.Add(orgDetailList[0].OrganizationName);
                        }
                    }
                    catch (Exception e)
                    {
                        FileWriter.Instance.WriteToFile("Exception when retrieving OrgDetails:" + e.ToString());
                        Environment.Exit(1);
                    }
                }
            }
        }

        public void RetrieveOrgId()
        {
            if (m_authentication.ToLower().Equals("passport") == true)
            {
                bool foundOrganizationMatch = false;

                CrmDiscoveryService discService = CreateDiscoveryService(m_authentication);
                
                RetrieveOrganizationsRequest orgReq = new RetrieveOrganizationsRequest();
                try
                {
                    orgReq.PassportTicket = GetPassportTicket(RetrievePolicy(), (string)m_userNames[0], (string)m_userPasswords[0], m_partner);
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile("Exception from GetPassportTicket:" + e.ToString());
                    Environment.Exit(1);
                }

                RetrieveOrganizationsResponse orgResp;
                try
                {
                    orgResp = (RetrieveOrganizationsResponse)discService.Execute(orgReq);
                    OrganizationDetail[] orgDetailList = orgResp.OrganizationDetails;

                    if (orgDetailList.Length == 0)
                    {
                        throw new Exception("OrgDetails had a length of Zero, Unexpected.");
                    }

                    for (int i = 0; i < orgDetailList.GetLength(0); i++)
                    {
                        if (orgDetailList[i].OrganizationName.ToLower().Equals(m_organizationName.ToLower()))
                        {
                            m_organizationId = orgDetailList[i].OrganizationId;
                            foundOrganizationMatch = true;
                            if (m_organizationId == Guid.Empty)
                            {
                                throw new Exception("Empty Guid for OrganizationId when name was matched");
                            }
                            break;
                        }
                    }    
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile("Exception when retrieving OrgDetails:" + e.ToString());
                    Environment.Exit(1);
                }
                if (foundOrganizationMatch == false)
                {
                    FileWriter.Instance.WriteToFile("No matches to organization name " + m_organizationName + " were found.");
                }
            }
            else if (m_authentication.ToLower().Equals("ad") == true)
            {
                bool foundOrganizationMatch = false;
                CrmDiscoveryService discService = CreateDiscoveryService(m_authentication);

                NetworkCredential creds = new NetworkCredential((string)m_userNames[0],(string)m_userPasswords[0], m_domain);
                discService.Credentials = creds;

                RetrieveOrganizationsRequest orgReq = new RetrieveOrganizationsRequest();
                try
                {
                    orgReq.UserId = m_domain + "\\" + (string)m_userNames[0];
                    orgReq.Password = (string)m_userPasswords[0];
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile("Exception when adding UserId and Pwd to orgRequest:" + e.ToString());
                }

                RetrieveOrganizationsResponse orgResp;
                try
                {
                    orgResp = (RetrieveOrganizationsResponse)discService.Execute(orgReq);
                    OrganizationDetail[] orgDetailList = orgResp.OrganizationDetails;

                    if (orgDetailList.Length == 0)
                    {
                        FileWriter.Instance.WriteToFile("OrgDetails had a length of Zero, Unexpected.");
                    }

                    for (int i = 0; i < orgDetailList.GetLength(0); i++)
                    {
                        if (orgDetailList[i].OrganizationName.ToLower().Equals(m_organizationName.ToLower()))
                        {
                            m_organizationId = orgDetailList[i].OrganizationId;
                            foundOrganizationMatch = true;
                            if (m_organizationId == Guid.Empty)
                            {
                                throw new Exception("Empty Guid for OrganizationId when name was matched");
                            }
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile("Exception when retrieving OrgDetails:" + e.ToString());
                }
                if (foundOrganizationMatch == false)
                {
                    FileWriter.Instance.WriteToFile("No matches to organization name " + m_organizationName + " were found.");
                }
            }
        }

        public void ReadAuthentication()
        {
            if (false == m_authentication.ToLower().Equals("ad"))
                return;

            XmlNode userGroups = m_root.SelectSingleNode("userGroups");
            if (userGroups != null)
            {
                try
                {
                    if (userGroups.Attributes["authentication"] != null)
                    {
                        m_authentication = userGroups.Attributes["authentication"].Value;
                        if (m_authentication.ToLower().Equals("ad") == false && m_authentication.ToLower().Equals("passport") == false)
                        {
                            throw new Exception();
                        }
                    }
                }
                catch
                {
                    FileWriter.Instance.WriteToFile("Authentication preference is in wrong format");
                }
            }
        }
		

		public void CreateEntityTemplates (XmlNodeList entityList, ArrayList container)
		{
			for(int i = 0 ; i < entityList.Count; i++)
			{
				XmlNode entityNode = entityList[i];
				CrmEntityTemplate entityTemplateObj = CrmEntityTemplate.GetCrmEntityTemplate(entityNode.Name);
				if( entityTemplateObj != null)
				{
					container.Add(entityTemplateObj);
					entityTemplateObj.ProcessExplicitElements(entityNode.Attributes);
					CreateEntityTemplates (entityNode.ChildNodes, entityTemplateObj.ChildTemplateList);
				}
			}
		}

		[System.Runtime.CompilerServices.MethodImpl (System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
		public void FireThreads ()
		{
			int usersPerThread = m_userNames.Count / m_numberOfThreads;

			if(usersPerThread == 0)
			{
				m_numberOfThreads = m_userNames.Count;
				usersPerThread = 1;
			}
			ArrayList workerThreads = new ArrayList();
			for(int i = 0; i < m_numberOfThreads; i++)
			{
				int workerStartUser = i * usersPerThread;
				int workerStopUser = (i == m_numberOfThreads - 1) ? m_userNames.Count : workerStartUser + usersPerThread - 1;
				ImpersonatedCreator impersonatedCreator = new ImpersonatedCreator(workerStartUser, workerStopUser, this);
				Thread workerThread = new Thread(new ThreadStart(impersonatedCreator.Run));
				workerThread.SetApartmentState(ApartmentState.STA);
				workerThread.Start ();
				workerThreads.Add (workerThread);
			}
			for(int i = 0; i < m_numberOfThreads; i++)
			{
				((Thread)workerThreads[i]).Join();
			}
		}

	}

	public class ImpersonatedCreator
	{
		private int m_startIndex;
		private int m_endIndex;
		private DbPopulator m_dbPopulator;

		private static WindowsImpersonationContext m_impersonationContext;

		private string m_userName;
		private string m_userPass;
		private string m_Domain;
        private string m_orgName;
		private System.Net.NetworkCredential m_currentUserCredentials;
		private CrmService m_crmService;
		private string m_Id;

		private TagManager m_tagManager;

		// dbpop perfmon counters
		public PerformanceCounter m_crmEntCrtTm;

		public TagManager TagManager
		{
			get
			{
				return m_tagManager;
			}
		}

		public string Id
		{
			get
			{
				return m_Id;
			}
		}

		public System.Net.NetworkCredential CurrentUserCredential
		{
			get
			{
				return m_currentUserCredentials;
			}
		}

		public CrmService CrmService
		{
			get
			{
				return m_crmService;
			}
		}

		public DbPopulator DbPopulator
		{
			get
			{
				return m_dbPopulator;
			}
		}

        public string OrgName
        {
            get
            {
                return m_orgName;
            }
            set
            {
                m_orgName = value;
            }
        }

        public string UserName
        {
            get
            {
                return m_userName;
            }
        }

        public string UserPassword
        {
            get
            {
                return m_userPass;
            }
        }

		[DllImport ("advapi32.dll", CharSet=CharSet.Auto )]
		private static extern bool LogonUser (string lpszUsername, string lpszDomain, string lpszPassword,
			uint dwLogonType, uint dwLogonProvider, out IntPtr phToken);
		[DllImport ("kernel32.dll")]
		private static extern bool CloseHandle (IntPtr token);

		public ImpersonatedCreator(int start, int end, DbPopulator dbPopulator)
		{
			m_startIndex = start;
			m_endIndex = end;
			m_dbPopulator = dbPopulator;
					
			// Perfmon entity creation counter
			m_crmEntCrtTm = new PerformanceCounter();
			m_crmEntCrtTm.CategoryName = "CrmPrfCntrs";
			m_crmEntCrtTm.ReadOnly = false;
		}

		public void Run()
		{
			int i;
			while((i = m_dbPopulator.GetCurrentIdx()) >= 0)
			{
                // Create TagManager for the new user so that user's objects are maintained for him alone.
                m_tagManager = new TagManager(m_dbPopulator, this);

				m_userName = (string)m_dbPopulator.UserNames[i];
				m_userPass = (string)m_dbPopulator.Passwords[i];
                m_orgName = (string)m_dbPopulator.OrganizationNames[i];
				m_Domain = m_dbPopulator.Domain;
                //m_orgName = m_dbPopulator.OrganizationName;

				Console.WriteLine("Creating entities for {0}", m_userName);

				if(!ImpersonateUser())
				{
					Console.WriteLine("Unable to impersonate as user {0} with password {1} for domain {2}",
						m_userName,
						m_userPass,
						m_Domain);
					return;
				}
                if (!SetupWebService())
                {
                    Console.WriteLine("Unable to setup webservice for user {0} with password {1} for domain {2}",
                        m_userName,
                        m_userPass,
                        m_Domain);
                    return;
                }

                if (!CreateLocalCache())
                {
                    Console.WriteLine("Retrieval of globalTag data for user {0} failed.", m_userName);
                    return;
                }

                int userStart = System.Environment.TickCount;

                CreateEntities();
                
                int userEnd = System.Environment.TickCount;
                Console.WriteLine("User {0} took {1} ms", m_userName, userEnd - userStart);

				RevertContext();

                // Release the TagManager for the user so that we don't use his entities for other users.
                m_tagManager = null;
			}
		}

        public bool CreateLocalCache()
        {
            bool retrieveSuccess = false;
            XmlNode globalTags = m_dbPopulator.Root.SelectSingleNode("globalTags");
            if (globalTags != null)
            {
                XmlNodeList tags = globalTags.SelectNodes("tag");
                for (int i = 0; i < tags.Count; i++)
                {
                    XmlNode tag = tags[i];
                    retrieveSuccess = m_tagManager.Retrieve(tag);
                    if (!retrieveSuccess)
                    {
                        return false;
                    }
                }
                return true;
            }
            return true;
        }

		public bool SetupWebService ()
		{
            string crmTicket = "";
            if (m_dbPopulator.AuthenticationScheme.ToLower().Equals("passport"))
            {
                try
                {
                    // Need to get the CrmTicket
                    CrmDiscoveryService discService = m_dbPopulator.CreateDiscoveryService(m_dbPopulator.AuthenticationScheme);
                    RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();
                    ticketRequest.OrganizationName = m_orgName; // m_dbPopulator.OrganizationName;

                    ticketRequest.PassportTicket = m_dbPopulator.GetPassportTicket(m_dbPopulator.RetrievePolicy(), m_userName, m_userPass, m_dbPopulator.Partner);
                    RetrieveCrmTicketResponse ticketResponse = (RetrieveCrmTicketResponse)discService.Execute(ticketRequest);

                    crmTicket = ticketResponse.CrmTicket;
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile("Exception during setup of CrmService:" + e.ToString());
                    return false;
                }
            }

			m_crmService = new CrmService();
			m_crmService.UnsafeAuthenticatedConnectionSharing = true;
			m_crmService.Url = m_dbPopulator.WebServiceUrl;
			m_crmService.ConnectionGroupName = WindowsIdentity.GetCurrent().Name;
			m_crmService.Credentials = m_currentUserCredentials;
            CrmAuthenticationToken token = new CrmAuthenticationToken();
            token.OrganizationName = m_orgName;
            if (m_dbPopulator.AuthenticationScheme.ToLower().Equals("ad"))
            {
                token.AuthenticationType = AuthenticationType.AD;
            }
            else if (m_dbPopulator.AuthenticationScheme.ToLower().Equals("passport"))
            {
                token.AuthenticationType = AuthenticationType.Passport;
                token.CrmTicket = crmTicket;
            }
            m_crmService.CrmAuthenticationTokenValue = token;
            return true;
		}

		public bool ImpersonateUser()
		{
			IntPtr hToken;
			if (m_Domain == null)
			{
				string currname = Environment.MachineName;
				string currdomainname = string.Empty;
        
				IPHostEntry ihe = System.Net.Dns.GetHostEntry(currname);
				if(ihe.HostName.Length > currname.Length)
				{
					if(ihe.HostName.ToLower().IndexOf(currname.ToLower()) >= 0) 
					{
						currdomainname = ihe.HostName.Remove (0, currname.Length + 1);
					}
					else
					{
						Console.WriteLine("Could not locate the current domain");
						throw new Exception("Could not locate the current domain");
					}
				}
				else
				{
					Console.WriteLine("Could not locate the current domain");
					return false;
				}
				m_Domain = currdomainname;
    			
				//userDomain = System.Environment.UserDomainName;
				Console.WriteLine("Working in domain - {0}", m_Domain);
			}

            CrmService crmService = new CrmService();

            if(m_dbPopulator.AuthenticationScheme.ToLower().Equals("ad"))
            {
			    bool successfulLogon = LogonUser(m_userName, m_Domain, m_userPass,3,0,out hToken);

                if (successfulLogon)
                {
                    WindowsIdentity ImpersonatedIdentity = new WindowsIdentity(hToken);
                    m_impersonationContext = ImpersonatedIdentity.Impersonate();
                    CloseHandle(hToken);
                    m_currentUserCredentials = new NetworkCredential(m_userName, m_userPass, m_Domain);              

                    //Creating UserAuth and Id				                    
                    crmService.UnsafeAuthenticatedConnectionSharing = true;
                    crmService.Credentials = m_currentUserCredentials;
                    crmService.ConnectionGroupName = WindowsIdentity.GetCurrent().Name;
                    crmService.Url = m_dbPopulator.WebServiceUrl;

                    CrmAuthenticationToken token = new CrmAuthenticationToken();
                    token.OrganizationName = m_orgName;
                    token.AuthenticationType = AuthenticationType.AD;
                    
                    crmService.CrmAuthenticationTokenValue = token;
                }
                else 
			    {				    
				    return false;
			    }
            }
            else if (m_dbPopulator.AuthenticationScheme.ToLower().Equals("passport"))
            {
                string crmTicket = "";

                try
                {
                    // Need to get the CrmTicket
                    CrmDiscoveryService discService = m_dbPopulator.CreateDiscoveryService(m_dbPopulator.AuthenticationScheme);
                    RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();
                    ticketRequest.OrganizationName = m_orgName; // m_dbPopulator.OrganizationName;
                    // TODO: Need to find the Passport Site Domain for the next call
                    ticketRequest.PassportTicket = m_dbPopulator.GetPassportTicket(m_dbPopulator.RetrievePolicy(), m_userName, m_userPass, m_dbPopulator.Partner);
                    RetrieveCrmTicketResponse ticketResponse = (RetrieveCrmTicketResponse)discService.Execute(ticketRequest);

                    crmTicket = ticketResponse.CrmTicket;
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile(e.ToString());
                    return false;
                }
                //Creating UserAuth and Id
                crmService.UnsafeAuthenticatedConnectionSharing = true;
                //crmService.Credentials = m_currentUserCredentials;
                crmService.ConnectionGroupName = WindowsIdentity.GetCurrent().Name;
                crmService.Url = m_dbPopulator.WebServiceUrl;
                CrmAuthenticationToken token = new CrmAuthenticationToken();
                token.OrganizationName = m_orgName;
                
                token.AuthenticationType = AuthenticationType.Passport;
                token.CrmTicket = crmTicket;
                
                crmService.CrmAuthenticationTokenValue = token;                    
            }
		    WhoAmIRequest whoAmIRequest = new WhoAmIRequest();
			try
			{
				Microsoft.Crm.Sdk.Proxy.Response response = crmService.Execute(whoAmIRequest);
				WhoAmIResponse whoAmIResponse = response as WhoAmIResponse;

				if(whoAmIResponse != null)
				{
					m_Id = whoAmIResponse.UserId.ToString();
				}
			}
			catch (Exception e)
			{
				Console.WriteLine("WhoAmI Authentication error: " + e.Message);
                if (m_impersonationContext != null)
                {
                    m_impersonationContext.Undo();
                }
				return false;
			}
				
			return true;
			
        }	

		
		public void CreateEntities ()
		{
			for(int i = 0; i < m_dbPopulator.EntityTemplateList.Count; i++)
			{
				CrmEntityTemplateExecContext topEntityExecContext = new CrmEntityTemplateExecContext((CrmEntityTemplate)m_dbPopulator.EntityTemplateList[i], null, this);
				topEntityExecContext.Create ();
			}
		}

		public void RevertContext()
		{
            if(m_impersonationContext != null)
    			m_impersonationContext.Undo ();
		}
	}

	public class TagManager
	{
		private Hashtable m_tagsInfo;
		private DbPopulator m_dbPopulator;
        private ImpersonatedCreator m_impersonatedCreator;

		private ColumnSet m_columnSet;
		private QueryByAttribute m_queryByAtt;

		public TagManager(DbPopulator dbPopulator, ImpersonatedCreator impersonatedCreator)
		{
			m_tagsInfo = new Hashtable();
			m_dbPopulator = dbPopulator;
            m_impersonatedCreator = impersonatedCreator;
			m_columnSet = new ColumnSet();
			m_queryByAtt = new QueryByAttribute ();
		}

		public bool Retrieve(XmlNode tag)
		{
			string [] queryColumns;

			Tag tagObj = new Tag();
			
			// Capture TagName
			tagObj.TagName = tag.Attributes["name"].Value;

			XmlNode query = tag.SelectSingleNode("query");
			// Capture EntityName
			XmlNode entityNameNode = query.SelectSingleNode("entity");
			if(entityNameNode == null)
			{
				FileWriter.Instance.WriteToFile(string.Format("EntityName for tag {0} is missing", tagObj.TagName));
                return false;
			}
			else
			{
				tagObj.EntityName = entityNameNode.Attributes["name"].Value;
			}

			// Capture columns
			XmlNodeList columns = query.SelectNodes("column");
			queryColumns = new string[columns.Count];
			for(int i = 0; i < columns.Count; i++)
			{
				queryColumns[i] = columns[i].Attributes["name"].Value;
				tagObj.ColumnAdd(columns[i].Attributes["name"].Value);
			}

			// Capture filter
			XmlNode filterNode = query.SelectSingleNode("filter");

            string crmTicket = "";
            if (m_dbPopulator.AuthenticationScheme.ToLower().Equals("passport"))
            {
                try
                {
                    // Need to get the CrmTicket
                    CrmDiscoveryService discService = m_dbPopulator.CreateDiscoveryService(m_dbPopulator.AuthenticationScheme);
                    RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();
                    ticketRequest.OrganizationName = m_impersonatedCreator.OrgName; // m_dbPopulator.OrganizationName;
                    // TODO: Need to find the Passport Site Domain for the next call
                    ticketRequest.PassportTicket = m_dbPopulator.GetPassportTicket(m_dbPopulator.RetrievePolicy(), (string)m_dbPopulator.UserNames[0], (string)m_dbPopulator.Passwords[0], m_dbPopulator.Partner);
                    RetrieveCrmTicketResponse ticketResponse = (RetrieveCrmTicketResponse)discService.Execute(ticketRequest);

                    crmTicket = ticketResponse.CrmTicket;
                }
                catch (Exception e)
                {
                    FileWriter.Instance.WriteToFile(e.ToString());
                    return false;
                }
            }

			// Retrieve the information
            CrmService crmService = m_impersonatedCreator.CrmService;            

			QueryExpression query1 = new QueryExpression();
			query1.EntityName = tagObj.EntityName;
			ColumnSet columnSet = new ColumnSet();
			//columnSet.EntityName = tagObj.EntityName;
			columnSet.Attributes = queryColumns;
			query1.ColumnSet = columnSet;
			if(filterNode != null)
			{
				XmlNodeList conditionExpressions = filterNode.ChildNodes;
				ConditionExpression[] ceArray = new ConditionExpression[conditionExpressions.Count];
				for(int ceCount = 0; ceCount < conditionExpressions.Count; ceCount++)
				{
					XmlNode conditionExpression = conditionExpressions[ceCount];
					ConditionExpression ce = new ConditionExpression();
					ce.AttributeName = conditionExpression.Attributes["attributename"].Value;
					ce.Operator = RetrieveOperator(conditionExpression.Attributes["operator"].Value);
					ce.Values = new object[] {conditionExpression.Attributes["value"].Value};
					ceArray[ceCount] = ce;
				}
				query1.Criteria = new FilterExpression();
				query1.Criteria.Conditions = ceArray;
			}

			try
			{
				tagObj.SetCollection(crmService.RetrieveMultiple(query1));
				// Add tabObj to hashtable
				m_tagsInfo.Add(tagObj.TagName,tagObj);
                return true;
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				FileWriter.Instance.WriteToFile(string.Format("{0}\r\nSoap Exception Detail: {1}",ex.ToString(),ex.Detail.InnerXml));
                return false;
			}
		}

		public ConditionOperator RetrieveOperator(string operatorString)
		{
			switch (operatorString)
			{
				case "equal" :
					return ConditionOperator.Equal;
				default :
					Console.WriteLine("Condition Operator specified not done");
					return ConditionOperator.Equal;
			}
		}

		public Hashtable TagsInfo
		{
			get
			{
				return m_tagsInfo;
			}
		}

		public void settag (TagNodeData tNode, CrmEntityTemplate entityTemplate, string entityId, CrmService crmService)
		{
			string tagIdentifier = tNode.TagIdentifier;
			string attributeName = tNode.TagAttribute;
			string tagEntityName = tNode.EntityName;

			Type templateType = entityTemplate.EntityType;

			Tag tag;
			if(m_tagsInfo.ContainsKey(tNode.TagIdentifier))
			{
				tag = (Tag)m_tagsInfo[tNode.TagIdentifier];
			}
			else
			{
				tag = new Tag();
				tag.TagName = tagIdentifier;
			}
		
			if(attributeName.Equals("entityid"))
			{
				tag.SetDynTagValue(entityId);
			}
			else
			{
				BusinessEntity retrievedEntity;
				if(attributeName == "all")
				{
					AllColumns all_columnSet = new AllColumns();
                    try
                    {
                        retrievedEntity = crmService.Retrieve(tagEntityName, new Guid(entityId), all_columnSet);
                    }
                    catch (System.Web.Services.Protocols.SoapException ex)
                    {
                        string err = string.Format("{0}\r\n", ex.ToString());
                        err = err + string.Format("Soap Exception Detail while retrieving entity: {0}\r\n", ex.Detail.InnerXml);
                        FileWriter.Instance.WriteToFile(err);
                        return;
                    }
				}
				else
				{
					m_columnSet.Attributes = new string [] {attributeName};
                    try
                    {
                        retrievedEntity = crmService.Retrieve(tagEntityName, new Guid(entityId), m_columnSet);
                    }
                    catch (System.Web.Services.Protocols.SoapException ex)
                    {
                        string err = string.Format("{0}\r\n", ex.ToString());
                        err = err + string.Format("Soap Exception Detail while retrieving entity: {0}\r\n", ex.Detail.InnerXml);
                        FileWriter.Instance.WriteToFile(err);
                        return;
                    }
				}
				BusinessEntityCollection retrievedCollection = new BusinessEntityCollection();
				retrievedCollection.BusinessEntities = new BusinessEntity [] {retrievedEntity};
				tag.SetCollection(retrievedCollection);
			}

			if(m_tagsInfo.ContainsKey(tNode.TagIdentifier))
				m_tagsInfo[tNode.TagIdentifier] = tag;
			else
				m_tagsInfo.Add(tNode.TagIdentifier,tag);
		}

		public void settype(TagNodeData tNode, CrmEntityTemplate entityTemplate, string entityId, CrmService crmService)
		{
            if (!m_tagsInfo.ContainsKey(tNode.TagIdentifier))
            {
                Tag tag = new Tag(1);
                tag.SetDynTagValue(entityTemplate.CrmEntityType);
                m_tagsInfo.Add(tNode.TagIdentifier, tag);
            }			
		}

		public void settag_filter(TagNodeData tNode, CrmEntityTemplate entityTemplate, string entityId, CrmService crmService)
		{
			string tagIdentifier = tNode.TagIdentifier;
			Tag tag;
			if(m_tagsInfo.ContainsKey(tNode.TagIdentifier))
			{
				tag = (Tag)m_tagsInfo[tNode.TagIdentifier];
			}
			else
			{
				tag = new Tag();
			}

			m_queryByAtt.EntityName = tNode.EntityName;
			AllColumns all_columns = new AllColumns();
			if(tNode.TagAttribute == "all")
			{
				m_queryByAtt.ColumnSet = all_columns;	
			}
			else
			{
				m_columnSet.Attributes = new string [] { tNode.TagAttribute };		
				m_queryByAtt.ColumnSet = m_columnSet;
			}
			m_queryByAtt.Attributes = new string [] { tNode.Filter };
			m_queryByAtt.Values = new string [] { entityId };

            try
            {
                BusinessEntityCollection collection = crmService.RetrieveMultiple(m_queryByAtt);
                tag.SetCollection(collection);
            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {
                string err = string.Format("{0}\r\n", ex.ToString());
                err = err + string.Format("Soap Exception Detail while retrieving entity: {0}\r\n", ex.Detail.InnerXml);
                FileWriter.Instance.WriteToFile(err);
                return;
            }
			
			if(m_tagsInfo.ContainsKey(tNode.TagIdentifier))
				m_tagsInfo[tNode.TagIdentifier] = tag;
			else
				m_tagsInfo.Add(tNode.TagIdentifier, tag);

		}
	}

	public class Tag
	{
		private string m_entityName;
		private string m_tagName;
		private ArrayList m_columns;
		private string m_filter;

		private ArrayList m_collection;
		private ArrayList m_dynTagValue;
		private int m_pos;
		private int m_collectionPos;
        private int m_capacity;

		private Random m_random;
		
		public Tag()
		{
			m_columns = new ArrayList();
			m_random = new Random(Thread.CurrentThread.GetHashCode()+ System.Environment.TickCount);
			m_dynTagValue = new ArrayList();
			m_collection = new ArrayList();
			m_pos = 0;
			m_collectionPos = 0;
            m_capacity = 100000;
		}

        public Tag(int capacity)
        {
            m_columns = new ArrayList();
            m_random = new Random(Thread.CurrentThread.GetHashCode() + System.Environment.TickCount);
            m_dynTagValue = new ArrayList(capacity);
            m_collection = new ArrayList(capacity);
            m_pos = 0;
            m_collectionPos = 0;
            m_capacity = capacity;
        }		

		public void SetDynTagValue(string a)
		{
            if (m_dynTagValue.Count == m_capacity)
            {
                if (m_pos == m_capacity)
                {
                    m_pos = 0;
                }
                m_dynTagValue.Insert(m_pos++, a);
            }
            else
            {
                m_dynTagValue.Add(a);
                m_pos++;
            }
            
		}

		public string GetDynTagValue()
		{            
            if (m_dynTagValue.Count == 0)
                return null;
            if (m_pos == 0)
            {
                return ((string)m_dynTagValue[m_dynTagValue.Count - 1]);
            }
            else
            {
                return ((string)m_dynTagValue[m_pos - 1]);
            }
		}

		public string TagName
		{
			get
			{
				return m_tagName;
			}
			set
			{
				m_tagName = value;
			}
		}

		public string EntityName
		{
			get
			{
				return m_entityName;
			}
			set
			{
				m_entityName = value;
			}
		}

		public string Filter
		{
			get
			{
				return m_filter;
			}
			set
			{
				m_filter = value;
			}
		}		

		public void SetCollection (BusinessEntityCollection collection)
		{            
            if (m_collection.Count == m_capacity)
            {
                if (m_collectionPos == m_capacity)
                {
                    m_collectionPos = 0;
                }
                m_dynTagValue.Insert(m_collectionPos++, collection);
            }
            else
            {
                m_collection.Add(collection);
                m_collectionPos++;
            }
		}

		public BusinessEntityCollection GetCollection()
		{          
            if (m_collection.Count == 0)
                return null;
            if (m_collectionPos == 0)
                return ((BusinessEntityCollection)m_collection[m_collection.Count - 1]);
            else
                return ((BusinessEntityCollection)m_collection[m_collectionPos - 1]);
		}

		public void ColumnAdd(object a)
		{
			m_columns.Add(a);
		}

		public string getlast(string attributeName, string filterName, string filterVal)
		{
			string [] split = attributeName.Split(new char [] {'.'});

			if(attributeName == "entityid")
			{
				return (string)m_dynTagValue[m_random.Next(m_dynTagValue.Count)];
			}

			BusinessEntityCollection businessEntityCollection = GetCollection();
			BusinessEntity randomBusinessEntity = (businessEntityCollection.BusinessEntities[m_random.Next(businessEntityCollection.BusinessEntities.Length - 1)]);
			Type m_type = randomBusinessEntity.GetType();
			object iteratingObject = (object)randomBusinessEntity;

			for(int i = 0; i < split.Length; i++)
			{
				PropertyInfo fi = m_type.GetProperty(split[i]);
				if(fi != null)
				{
					iteratingObject = fi.GetValue(iteratingObject,null);
					m_type = iteratingObject.GetType();
				}
				else
				{
					FileWriter.Instance.WriteToFile(string.Format("Attribute name {0} does not exist in {1}", split[i], m_type.Name));
					return null;
				}
			}
			string returnVal = iteratingObject.ToString();
			return returnVal;
		}

		public string getconstraints(string attributename, string filter, string filterVal)
		{
			string constraints = 
				  @"<Constraints><Constraint><Expression><Body>{0}</Body><Parameters><Parameter name=""resource""></Parameter></Parameters></Expression></Constraint></Constraints>";

			string expression = string.Empty;

            if (attributename == "entityid")
            {
                for (int i = 0; i < m_dynTagValue.Count; i++)
                {
                    expression += string.Format(CultureInfo.InvariantCulture,
                        "resource[\"id\"] == {0}{1}{2} || ", "{", m_dynTagValue[i], "}");
                }
            }
            else
            {
                string[] split = attributename.Split(new char[] { '.' });

                BusinessEntityCollection businessEntityCollection = (BusinessEntityCollection)m_collection[m_random.Next(m_collection.Count)];
                for (int p = 0; p < businessEntityCollection.BusinessEntities.Length; p++)
                {
                    BusinessEntity randomBusinessEntity = (businessEntityCollection.BusinessEntities[p]);
                    Type m_type = randomBusinessEntity.GetType();
                    object iteratingObject = (object)randomBusinessEntity;

                    for (int i = 0; i < split.Length; i++)
                    {
                        PropertyInfo fi = m_type.GetProperty(split[i]);
                        if (fi != null)
                        {
                            iteratingObject = fi.GetValue(iteratingObject, null);
                            m_type = iteratingObject.GetType();
                        }
                        else
                        {
                            FileWriter.Instance.WriteToFile(string.Format("Attribute name {0} does not exist in {1}", split[i], m_type.Name));
                            return null;
                        }
                    }
                    string returnVal = iteratingObject.ToString();
                    expression += string.Format(CultureInfo.InvariantCulture,
                        "resource[\"id\"] == {0}{1}{2} || ", "{", returnVal, "}");
                }
            }

			if (expression.Length >= 4)
			{
				expression = expression.Remove(expression.Length - 4, 4);
			}

			return string.Format(CultureInfo.InvariantCulture,
				constraints, expression);
		}

		public string getactivityparties(string attributename, string filter, string filterVal)
		{
			string activityparty = @"[{0},{1}]";

            if (attributename == "entityid")
            {
                return string.Format(CultureInfo.InvariantCulture,
                activityparty, m_dynTagValue[m_random.Next(m_dynTagValue.Count)], "equipment");
            }

            string[] split = attributename.Split(new char[] { '.' });

            BusinessEntityCollection businessEntityCollection = (BusinessEntityCollection)m_collection[m_random.Next(m_collection.Count)];
            BusinessEntity randomBusinessEntity = (businessEntityCollection.BusinessEntities[m_random.Next(businessEntityCollection.BusinessEntities.Length - 1)]);
            Type m_type = randomBusinessEntity.GetType();
            object iteratingObject = (object)randomBusinessEntity;

            for (int i = 0; i < split.Length; i++)
            {
                PropertyInfo fi = m_type.GetProperty(split[i]);
                if (fi != null)
                {
                    iteratingObject = fi.GetValue(iteratingObject, null);
                    m_type = iteratingObject.GetType();
                }
                else
                {
                    FileWriter.Instance.WriteToFile(string.Format("Attribute name {0} does not exist in {1}", split[i], m_type.Name));
                    return null;
                }
            }
            string returnVal = iteratingObject.ToString();
            return string.Format(CultureInfo.InvariantCulture,
                activityparty, returnVal, "equipment");			
		}


		public string getrandom(string attributeName, string filterName, string filterVal)
		{
			string [] split = attributeName.Split(new char [] {'.'});

			if(attributeName == "entityid")
			{
				return (string)m_dynTagValue[m_random.Next(m_dynTagValue.Count)];
			}

			BusinessEntityCollection businessEntityCollection = (BusinessEntityCollection)m_collection[m_random.Next(m_collection.Count)];
			BusinessEntity randomBusinessEntity = (businessEntityCollection.BusinessEntities[m_random.Next(businessEntityCollection.BusinessEntities.Length - 1)]);
			Type m_type = randomBusinessEntity.GetType();
			object iteratingObject = (object)randomBusinessEntity;

			for(int i = 0; i < split.Length; i++)
			{
				PropertyInfo fi = m_type.GetProperty(split[i]);
				if(fi != null)
				{
					iteratingObject = fi.GetValue(iteratingObject,null);
					m_type = iteratingObject.GetType();
				}
				else
				{
					FileWriter.Instance.WriteToFile(string.Format("Attribute name {0} does not exist in {1}", split[i], m_type.Name));
					return null;
				}
			}
			string returnVal = iteratingObject.ToString();
			return returnVal;
		}

		public string getfiltered(string attributeName, string filterName, string filterVal)
		{
			string [] split = filterName.Split(new char[] {'.'});
			string [] split2 = attributeName.Split(new char[] {'.'});

			for(int p = 0; p < m_collection.Count; p++)
			{
				BusinessEntityCollection businessEntityCollection = (BusinessEntityCollection)m_collection[p];
				for(int i = 0; i < businessEntityCollection.BusinessEntities.Length; i++)
				{
					BusinessEntity m_BusinessEntity = (businessEntityCollection.BusinessEntities[i]);
					Type m_type = m_BusinessEntity.GetType();
					object iteratingObject = (object)m_BusinessEntity;

					for(int j = 0; j < split.Length; j++)
					{
						PropertyInfo fi = m_type.GetProperty(split[j]);
						if(fi != null)
						{
							iteratingObject = fi.GetValue(iteratingObject,null);
							m_type = iteratingObject.GetType();
						}
						else
						{
							FileWriter.Instance.WriteToFile(string.Format("Attribute name {0} does not exist in {1}", split[j], m_type.Name));
							return null;
						}
					}
					string val = iteratingObject.ToString();
					if(val.Equals(filterVal))
					{
						Type type = m_BusinessEntity.GetType();
						object iteratingObject2 = (object)m_BusinessEntity;

						for(int j = 0; j < split2.Length; j++)
						{
							PropertyInfo fi = type.GetProperty(split2[j]);
							if(fi != null)
							{
								iteratingObject2 = fi.GetValue(iteratingObject2,null);
								type = iteratingObject2.GetType();
							}
							else
							{
								FileWriter.Instance.WriteToFile(string.Format("Attribute name {0} does not exist in {1}", split2[i], type.Name));
								return null;
							}
						}
						string returnVal = iteratingObject2.ToString();
						return returnVal;
					}
				}
			}
			return null;
		}	
	}

	 public class CrmEntityTemplateExecContext
	{
		protected CrmEntityTemplate m_entityTemplate;
		protected CrmEntityTemplateExecContext m_parent;
		protected ImpersonatedCreator m_creator;

		protected XmlDocument m_runTimeXml;
		protected Random m_randomInstance;
		protected string m_ownerId;
		protected ReplacementFunctions m_rFuncs;

		protected ArrayList m_RFList;
		protected ArrayList m_dynTagList;
		protected ArrayList m_tagList;

		// BusinessEntity needs to be in ExecContext as it should be thread safe.
		protected BusinessEntity m_entity;

		public XmlDocument RunTimeXml
		{
			get
			{
				return m_runTimeXml;
			}
		}

		public CrmEntityTemplateExecContext(CrmEntityTemplate entityTemplate, CrmEntityTemplateExecContext parent, ImpersonatedCreator creator)
		{
			m_entityTemplate = entityTemplate;
			m_entity = m_entityTemplate.GetBusinessEntity();
			m_parent = parent;
			m_creator = creator;
			m_runTimeXml = (XmlDocument)(entityTemplate.EntityXml).Clone();
			m_randomInstance = new Random (Thread.CurrentThread.GetHashCode() + System.Environment.TickCount);
			m_ownerId = creator.Id.ToString();
			m_RFList = new ArrayList();
			m_dynTagList = new ArrayList();
			m_tagList = new ArrayList();
			m_rFuncs = new ReplacementFunctions(m_ownerId,m_creator.DbPopulator);
		}

		public void Create()
		{
			int numberEntitiesCreated = 0;
			int entCrtTime=0;

			CreateReplacementNodes();
			CreateDynamicNodes();

			for(int i = 0; i < m_entityTemplate.Count; i++)
			{
				Replace();
				ReplaceDynTags();
                
				entCrtTime = System.Environment.TickCount;
				string entityId = m_entityTemplate.CreateEntity(m_runTimeXml, m_creator.CrmService, m_entity, m_creator.DbPopulator);
				entCrtTime = System.Environment.TickCount-entCrtTime;

				// Set perfmon Cntr to create time
				m_creator.m_crmEntCrtTm.CounterName = "EntityCrtTm";
				m_creator.m_crmEntCrtTm.RawValue = entCrtTime;
				
				try
				{
					m_creator.m_crmEntCrtTm.CounterName = m_runTimeXml.FirstChild.Name + "CrtTm";
					m_creator.m_crmEntCrtTm.RawValue = entCrtTime;
				}
				catch(Exception e)
				{
					Console.WriteLine("Performane Counter Exception:" + e.Message);
				}

				if(entityId == null)
					continue;

				SaveTag(entityId);

				numberEntitiesCreated++;
				for(int j = 0; j < m_entityTemplate.ChildTemplateList.Count; j++)
				{
					CrmEntityTemplateExecContext m_childExecContext = new CrmEntityTemplateExecContext((CrmEntityTemplate)m_entityTemplate.ChildTemplateList[j],this,m_creator);
					m_childExecContext.Create();
				}

				// Post create updates for the entity done after creation of child entities.
				m_entityTemplate.CallPostCreate(entityId, m_runTimeXml, m_creator.CrmService, m_creator.DbPopulator);
			}

            if(m_creator.DbPopulator.QuietMode != true)
    			Console.WriteLine("[{0}] Created {1} out of {2} {3}", m_creator.UserName, numberEntitiesCreated, m_entityTemplate.Count, m_runTimeXml.FirstChild.Name);
		}

		public void Replace()
		{
			for(int i = 0; i < m_RFList.Count; i++)
			{
				RFData rfData = (RFData)m_RFList[i];
				rfData.Replace(m_rFuncs);
			}
		}

		public void ReplaceDynTags()
		{
			for(int i = 0; i < m_dynTagList.Count; i++)
			{
				TagNodeData tnData = (TagNodeData)m_dynTagList[i];
				tnData.Replace(this);
			}

			for(int i = 0; i < m_tagList.Count; i++)
			{
				TagNodeData globalTnData = (TagNodeData) m_tagList[i];
				globalTnData.ReplaceGlobal(this);
			}
		}

		 public void CreateReplacementNodes()
		 {
			 XmlNodeList nodes = m_runTimeXml.SelectNodes("(//text()[contains(.,'replace')]|//@*[contains(.,'replace')])");
			 for (int i = 0; i < nodes.Count; i++)
			 {
				 RFData rfData = new RFData();
				 rfData.CreateData(nodes[i]);
				 m_RFList.Add(rfData);
			 }
			 nodes = m_runTimeXml.SelectNodes("(//text()[contains(.,'repfiltered')]|//@*[contains(.,'repfiltered')])");
			 for (int i = 0; i < nodes.Count; i++)
			 {
				 RFData rfData = new RFData();
				 rfData.CreateDataFiltered(nodes[i], m_runTimeXml);
				 m_RFList.Add(rfData);
			 }
		 }


		public void CreateDynamicNodes()
		{
			XmlNodeList nodes = m_runTimeXml.SelectNodes("(//text()[contains(.,'getdyntag')]|//@*[contains(.,'getdyntag')])");
			for(int i = 0 ; i < nodes.Count; i++)
			{
				TagNodeData tnData = new TagNodeData(m_creator);
				tnData.CreateData(nodes[i]);
				m_dynTagList.Add(tnData);
			}
			XmlNodeList globalTagNodes = m_runTimeXml.SelectNodes("(//text()[contains(.,'gettag')]|//@*[contains(.,'gettag')])");
			for(int i = 0; i < globalTagNodes.Count; i++)
			{
				TagNodeData globalTnData = new TagNodeData(m_creator);
				globalTnData.CreateGlobalTagData(globalTagNodes[i]);
				m_tagList.Add(globalTnData);
			}
		}

		public void SaveTag(string entityId)
		{
			for(int i = 0; i < m_entityTemplate.SaveTagInfoList.Count; i++)
			{
				TagNodeData tagNodeData = (TagNodeData)m_entityTemplate.SaveTagInfoList[i];
				Type tagType = ((TagManager)m_creator.TagManager).GetType();
				MemberInfo methodInfo = tagType.GetMethod(tagNodeData.FunctionName);
				object [] argsList = new object [] {tagNodeData, m_entityTemplate, entityId, m_creator.CrmService};

				if(methodInfo != null)
				{
					tagType.InvokeMember(methodInfo.Name,
						BindingFlags.DeclaredOnly | 
						BindingFlags.Public | 
						BindingFlags.NonPublic | 
						BindingFlags.Instance | 
						BindingFlags.InvokeMethod,
						null,
						((TagManager)m_creator.TagManager),
						argsList);
				}
			}
		}
	}

	public class ReplacementFunctions
	{
		[DllImport("Kernel32.dll")]
		public static extern bool QueryPerformanceCounter(
			out long lpPerformanceCount);

		private static char[] Alphabet = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcefghijklmnopqrstuvwxyz0123456789").ToCharArray();
		private static Random m_randomInstance = new Random(Thread.CurrentThread.GetHashCode() + System.Environment.TickCount);
		private const int STRING_RANDOMIZER_LENGTH = 3;
		private string m_ownerId;
        private Guid m_organizationId;

		private static string [] m_cities = new string[] {"Seattle", "Portland", "San Fransisco", "Sacramento", "Frezno", "Santa Barbara", "Los Angeles", "San Diego", "Las Vegas", "Phoenix", "San Antonio", "Minnessota", "Chicago", "New York", "Washington D.C.", "Houston", "Miami", "Anchorage", "Dallas", "Santa Clara", "San Jose", "Austin"};
        private static string [] m_states = new string[] { "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippe", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming" };
		private static string [] m_countries = new string[]{"United States"};
		private static string [] m_firstNames = new string [] {"Anthony", "John", "Bill", "Sam", "James", "Robert", "Mary", "Michael", "William", "David", "Mary", "Patricia", "Linda", "Barbara", "Elizebeth", "Jennifer", "Maria", "Susan", "Margaret", "Dorothy", "Lisa", "Nancy", "Karen", "Betty", "Helen", "Sandra", "Donna", "Carol", "Ruth", "Sharon", "David", "Richard", "Charles", "Joseph", "Thomas", "Christopher", "Daniel", "Paul", "Mark"};
		private static string [] m_lastNames = new string [] {"Smith", "Johnson", "Williams", "Jones", "Brown", "Davis", "Miller", "Wilson", "Moore", "Taylor", "Anderson", "Thomas", "Jackson", "White", "Harris", "Martin", "Thonpson", "Garcia", "Martinez", "Robinson"};
        private static string [] m_streetName = new string[] { "First Avenue West", "First Avenue East", "First Avenue North", "First Avenue South", "Second Avenue West", "Second Avenue East", "Second Avenue North", "Second Avenue South", "3rd Avenue East", "3rd Avenue West", "3rd Avenue North", "3rd Avenue South", "4th Avenue West", "4th Avenue East", "4th Avenue North", "4th Avenue South", "Broadway Avenue", "Denny Way", "West Lake Avenue", "East Lake Avenue" };
        private static string [] m_names = new string[] { "Bold Bike Accessories", "Cash and Carry Bikes", "Discount Bicycle Specialists", "Front Sporting Goods", "Full-Service Bike Store", "Grand Cycle Store", "Great Bicycle Supply", "Leading Bike Distributors", "Lots of Bikes Storehouse", "New and Used Bicycles", "Recreation Supplies", "Scooters and Bikes Store", "Specialty Sports Store", "The Cycle Store", "Weekend Tours", "Wide World Importers", "A Bike Store", "Advanced Bike Components", "Affordable Sports Equipment", "Curbside Sporting Goods", "Cycles and Scooters", "Daring Rides", "Distinctive Cycles Sales and Service", "Big-Time Bike Store", "Bike Boutique", "Bike Dealers Association", "Bike Experts", "Bike Products and Accessories", "Blue Bicycle Company", "Brown Bicycle Company", "Certified Bicycle Supply", "Coalition Bike Company",  };
        private static string [] m_sentences = new string[] {   "This is the description sentence. ",
                                                                "The description is trying to describe about the details. ",
                                                                "These details could have been missed in the summary part. ",
                                                                "The length of the description is variable. ",
                                                                "The sample data is from the bicycle industry. ",
                                                                "Eventually all these should be put in an xml file." };
        private static string[] m_subjects = new string[] {    "This is an important thing to remember",
                                                                "Remember to call",
                                                                "Need to send the quotation",
                                                                "Contacted the manager",
                                                                "Got this through a good lead", 
                                                                "Unable to contact",
                                                                "Need to follow up" };
        private static string[] m_campaigns = new string[] { "Summer Sale Campaign", "Winter Sale Campaign", "50% Discount Campaign", "25% Discount Campaign", "Fall Sale Campaign", "Upscale items marketing Campaign", "Bike parts liquidation Sale Campaign", "Boutique items Campaign", "Overstock clearance Campaign" };

        private static string[] m_discountlists = new string[] { "Summer Sale Discountlist", "Winter Sale Discountlist", "50% Discount Discountlist", "25% Discount Discountlist", "Fall Sale Discountlist", "Upscale items marketing Discountlist", "Bike parts liquidation Sale Discountlist", "Boutique items Discountlist", "Overstock clearance Discountlist" };

        private static string[] m_jobtitles = new string[] { "C.E.O", "C.F.O", "Vice President", "Marketing Executive", "Sales Manager", "Sales Person", "Customer Relationship Manager", "Assistant", "Administrator", "Developer", "Web Programmer", "Tester", "Architect", "Doctor", "Mechanic", "Pilot", "Police Officer", "Army Personnel" };

        private static string[] m_opportunities = new string[] { "Bold Bike Accessories opportunity", "Cash and Carry Bikes opportunity", "Discount Bicycle Specialists opportunity", "Front Sporting Goods opportunity", "Full-Service Bike Store opportunity", "Grand Cycle Store opportunity", "Great Bicycle Supply opportunity", "Leading Bike Distributors opportunity", "Lots of Bikes Storehouse opportunity", "New and Used Bicycles opportunity", "Recreation Supplies opportunity", "Scooters and Bikes Store opportunity", "Specialty Sports Store opportunity", "The Cycle Store opportunity", "Weekend Tours opportunity", "Wide World Importers opportunity", "A Bike Store opportunity", "Advanced Bike Components opportunity", "Affordable Sports Equipment opportunity", "Curbside Sporting Goods opportunity", "Cycles and Scooters opportunity", "Daring Rides opportunity", "Distinctive Cycles Sales and Service opportunity", "Big-Time Bike Store opportunity", "Bike Boutique opportunity", "Bike Dealers Association opportunity", "Bike Experts opportunity", "Bike Products and Accessories opportunity", "Blue Bicycle Company opportunity", "Brown Bicycle Company opportunity", "Certified Bicycle Supply opportunity", "Coalition Bike Company opportunity", };

		private static List<DateTime> m_starttimes = new List<DateTime>();
        
        private DbPopulator m_dbPop;

		private static void InitializeRandomStartTimes()
		{
			int i;

			// 120,000 appointments in the past (100% capacity)
			// 9,000 appointments over the next month (90% capacity)
			// 6,000 appointments over the next two months (60% capacity)
			// 12,000 appointments over the next 4 months (30% capacity)

			// Appointments are between 8AM and 5PM

			// appointments in the past
			for (i = 0; i < 41000; i++)
			{
				m_starttimes.Add(
					DateTime.Today.AddDays(-1 * m_randomInstance.Next(365)).AddHours(8 + m_randomInstance.Next(9)));
			}

			// appointments in the next month
			for (i = 0; i < 3600; i++)
			{
				m_starttimes.Add(
					DateTime.Today.AddDays(m_randomInstance.Next(30)).AddHours(8 + m_randomInstance.Next(9)));
			}

			// appointments in two months
			for (i = 0; i < 3600; i++)
			{
				m_starttimes.Add(
					DateTime.Today.AddMonths(1).AddDays(m_randomInstance.Next(30)).AddHours(8 + m_randomInstance.Next(9)));
			}

			//appointments in 6 months
			for (i = 0; i < 3600; i++)
			{
				m_starttimes.Add(
					DateTime.Today.AddMonths(2).AddDays(m_randomInstance.Next(120)).AddHours(8 + m_randomInstance.Next(9)));
			}
		}

		public ReplacementFunctions(string ownerId, DbPopulator dbPop)
		{
			m_ownerId = ownerId;
            m_dbPop = dbPop;
            m_organizationId = dbPop.OrganizationId;
		}

        static ReplacementFunctions()
        {
            InitializeRandomStartTimes();
        }

        public string randomguid()
        {
            Guid tempGuid = Guid.NewGuid();
            return tempGuid.ToString("B");
        }

		public string owneridreplace ()
		{
			return m_ownerId;
		}

        public string organizationidreplace()
        {
            return m_organizationId.ToString();
        }

		public string randomstring()
		{
			return randomstring("10","25");
		}

		public string randomstring(string min, string max)
		{
			int minLength = int.Parse(min);
			int maxLength = int.Parse(max);

			int alphabetLength = Alphabet.Length;
			int stringLength = m_randomInstance.Next(minLength, maxLength);
			char[] str = new char[stringLength];

			// This is necessary to avoid excessive random number generation when STRING_RANDOMIZER_LENGTH
			// is greater than the target string length
			int randomizerLength = stringLength < STRING_RANDOMIZER_LENGTH ? maxLength : STRING_RANDOMIZER_LENGTH;

			int[] rndInts = new int[randomizerLength];
			int[] rndIncrements = new int[randomizerLength];

			// Prepare a "randomizing" array
			for(int i=0; i < randomizerLength; i++)
			{
				int rnd = m_randomInstance.Next(alphabetLength);
				rndInts[i] = rnd;
				rndIncrements[i] = rnd;
			}

			// Generate "random" string out of the alphabet used
			for(int i=0; i < stringLength; i++)
			{
				int indexRnd = i % randomizerLength;
				int indexAlphabet = rndInts[indexRnd] % alphabetLength;
				str[i] = Alphabet[indexAlphabet];
                
				// Each rndInt "cycles" characters from the array, 
				// so we have more or less random string as a result
				rndInts[indexRnd] += rndIncrements[indexRnd];
			}
			long tickCount = 0;
			QueryPerformanceCounter(out tickCount);
			
			string retString = new string(str) + "-" + tickCount.ToString();
			return retString;
		}

		public string randomphone()
		{
			int area_code = 100 + m_randomInstance.Next(899);
			int first3 = 100 + m_randomInstance.Next(899);
			int last4 = m_randomInstance.Next(9999);

			return string.Format("({0:D3}) {1:D3}-{2:D4}", area_code, first3, last4);
		}

		public string randomurl ()
		{
			return "http://www.random" + m_randomInstance.Next(1000).ToString() + ".com";
		}

		public string randomemail ()
		{
			return "random" + m_randomInstance.Next(1000).ToString() + "@random.com";
		}

		public string randomnumber ()
		{
			return m_randomInstance.Next (100000).ToString ();
		}

		public string randomnumber(string min, string max)
		{
			return m_randomInstance.Next(int.Parse(min),int.Parse(max)).ToString();
		}

        public string getnextnumber()
        {
            return m_dbPop.GetCurrentCounter().ToString();
        }
        public string getnexttick()
        {
            long tickCount;
            QueryPerformanceCounter(out tickCount);
            return tickCount.ToString();            
        }

        public string getnextnumbertick()
        {
            long tickCount;
            QueryPerformanceCounter(out tickCount);
            string ticknum = getnextnumber() + " - " + tickCount.ToString();
            return ticknum;
        }

		public string randomtime()
		{
			DateTime a = DateTime.Today.AddDays((double)m_randomInstance.Next(30)) + TimeSpan.FromHours(8 + m_randomInstance.Next(8));
			return (a).ToString ("yyyy-MM-ddTHH:mm:ssZ");
		}

		public string randomdate(string numDaysString)
		{
			double numDays = double.Parse(numDaysString);
			return DateTime.Today.AddDays(numDays).ToString ("yyyy-MM-ddTHH:mm:ssZ");
		}

		public string randomdate()
		{
			double numDays = (double)m_randomInstance.Next(30);
			return DateTime.Today.AddDays(numDays).ToString ("yyyy-MM-ddTHH:mm:ssZ");
		}

		public string randomstarttime()
		{
			return m_starttimes[m_randomInstance.Next(m_starttimes.Count)].ToString("yyyy-MM-ddTHH:mm:ss");
		}

		public string randomstarttime(string startDate, string endDate)
		{
			DateTime start = DateTime.Parse(startDate);

			DateTime end = DateTime.Parse(endDate);

			TimeSpan delta = new TimeSpan (Math.Abs(end.Ticks - start.Ticks));

			DateTime randomStartTime = (start < end) ?
				start.AddTicks(m_randomInstance.Next(delta.Milliseconds)) :
				end.AddTicks(m_randomInstance.Next(delta.Milliseconds));

			return randomStartTime.ToString("yyyy-MM-ddTHH:mm:ss");
		}

		public string randomendtime(string duration, string starttime)
		{
			DateTime start = DateTime.Parse(starttime);
			DateTime end = DateTime.Parse(starttime);
			end = end + TimeSpan.FromMinutes(double.Parse(duration));
			return end.ToString("yyyy-MM-ddTHH:mm:ss");
		}

		public string randomfirstname()
		{
			return m_firstNames[m_randomInstance.Next(m_firstNames.Length - 1)];
		}

		public string randomlastname()
		{
			return m_lastNames[m_randomInstance.Next(m_lastNames.Length - 1)];
		}

		public string randomfullname()
		{
			string fullname = m_firstNames[m_randomInstance.Next(m_firstNames.Length - 1)] + " " + m_lastNames[m_randomInstance.Next(m_lastNames.Length - 1)];
			return fullname;
		}

		public string randomcity()
		{
			return m_cities[m_randomInstance.Next(m_cities.Length - 1)];
		}

		public string randomcountry()
		{
			return m_countries[m_randomInstance.Next(m_countries.Length - 1)];
		}

        public string randomaddressline1()
        {
            string addressline1 = randomnumber("1000", "10000") + " " + m_streetName[m_randomInstance.Next(m_streetName.Length - 1)];
            return addressline1;
        }

        public string randomname()
        {
            string name = "Branch : " + getnextnumbertick() + " - " + m_names[m_randomInstance.Next(m_names.Length - 1)];// + m_dbPop.GetCurrentCounter().ToString();
            return name;
        }

        public string randomdescription(string numberOfSentences)
        {
            string description = "";
            int number = int.Parse(numberOfSentences);
            
            if (number > m_sentences.Length)
                number = m_sentences.Length;

            for(int i = 0; i < number; i++)
            {
                description += m_sentences[i];
            }
            return description;
        }

        public string randomdescription()
        {
            return randomdescription("5");
        }

        public string randomstate()
        {
            return m_states[m_randomInstance.Next(m_states.Length - 1)];
        }

        public string randomsubject()
        {
            return m_subjects[m_randomInstance.Next(m_subjects.Length - 1)];
        }

        public string randomtext(string numberOfSentences)
        {
            string description = "";
            int number = int.Parse(numberOfSentences);

            if (number > m_sentences.Length)
                number = m_sentences.Length;

            for (int i = 0; i < number; i++)
            {
                description += m_sentences[m_randomInstance.Next(m_sentences.Length - 1)];
            }
            return description;
        }

        public string randomcampaign()
        {
            string campaign = m_campaigns[m_randomInstance.Next(m_campaigns.Length - 1)];
            return campaign;
        }

        public string randomdiscountlist()
        {
            long tickCount;
            QueryPerformanceCounter(out tickCount);
            string discountList = m_discountlists[m_randomInstance.Next(m_discountlists.Length - 1)] + " - " + tickCount.ToString();
            return discountList;
        }

        public string randomjobtitle()
        {
            return m_jobtitles[m_randomInstance.Next(m_jobtitles.Length)];
        }

        public string randomaddress()
        {
            string address = randomaddressline1() + ", " + randomcity() + ", " + randomstate() + " - " + randomnumber("10000", "99999") + ", " + randomcountry();
            return address;
        }

        public string randomopportunity()
        {
            long tickCount;
            QueryPerformanceCounter(out tickCount);
            string opp =  m_opportunities[m_randomInstance.Next(m_opportunities.Length - 1)] + " - " + tickCount.ToString();
            return opp;
        }

        public string randomproduct()
        {
            long tickCount;
            QueryPerformanceCounter(out tickCount);
            string[] color = new string[] { "Black", "White", "Red", "Yellow", "Green", "Blue", "Violet", "Orange" };
            string[] type = new string[] { "Mountain", "Road", "Cross Country", "High Shock", "Cruiser", "Sleek Look" };
            string product = type[m_randomInstance.Next(type.Length - 1)] + " - " + m_dbPop.GetCurrentCounter().ToString() + " : " + color[m_randomInstance.Next(color.Length - 1)] + ", " + m_dbPop.GetCurrentCounter().ToString() + " - " + tickCount.ToString();
            return product;
        }

        public string randomquote()
        {
            string quote = randomproduct() + " quote";
            return quote;
        }

        public string randomsalesorder()
        {
            string salesorder = randomproduct() + " order";
            return salesorder;
        }
    }

    public class TagNodeData
	{
		private XmlNode m_replacementNode;
		private ImpersonatedCreator m_creator;
		private string m_tagIdentifier;
		private string m_functionName;
		private string m_attributeName;

		private string m_entityName;
		private string m_filter;
		private string m_substitute;

		public XmlNode ReplacementNode
		{
			get
			{
				return m_replacementNode;
			}
			set
			{
				m_replacementNode = value;
			}
		}

		public string EntityName
		{
			get
			{
				return m_entityName;
			}
		}
		public string Filter
		{
			get
			{
				return m_filter;
			}
		}
		public string FunctionName
		{
			get
			{
				return m_functionName;
			}
		}
		public string TagIdentifier
		{
			get
			{
				return m_tagIdentifier;
			}
		}
		public string TagAttribute
		{
			get
			{
				return m_attributeName;
			}
		}

		public TagNodeData (ImpersonatedCreator creator)
		{
			m_creator = creator;
			m_filter = null;
			m_substitute = null;
		}

		public void CreateData(XmlNode dynTagNode)
		{            
			m_replacementNode = dynTagNode;
			string [] split = m_replacementNode.Value.Split(new char [] {'(', ',' , ')'});
			if(split.Length == 7)
			{
				try
				{
					m_tagIdentifier = split[1];
					m_functionName = split[2];
					m_attributeName = split[3];
					m_filter = split[4];
					m_substitute = split[5];
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Wrong format writing getdyntag(<tagIdentifier>, <functionName>, <attributeName>, <filterNameInEntity>, <filterNameinXML>");
				}
			}
			else if(split.Length == 5)
			{
				try
				{
					m_tagIdentifier = split[1];
					m_functionName = split[2];
					m_attributeName = split[3];
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Wrong format wrting getdyntag(<tagIdentifier>, <functionName>, <attributeName>");
				}
			}
			else
			{
				try
				{
					m_tagIdentifier = split[1];
				}
				catch
				{
					FileWriter.Instance.WriteToFile("Wrong format of writing getdyntag(<tagIdentifier>)");
				}
			}
		}

		public void CreateGlobalTagData (XmlNode tagNode)
		{
			m_replacementNode = tagNode;
			string [] split = m_replacementNode.Value.Split(new char [] {'(', ',' , ')'});
			try
			{
				if(split.Length > 5)
				{
					m_tagIdentifier = split[1];
					m_functionName = split[2];
					m_attributeName = split[3];
					m_filter = split[4];
					m_substitute = split[5];
				}
				else
				{
					m_tagIdentifier = split[1];
					m_functionName = split[2];
					m_attributeName = split[3];
				}
			}
			catch
			{
				FileWriter.Instance.WriteToFile("wrong format for writing gettag(<tagIdentifier>,<functionname>)");
			}
		}

		public void Replace(CrmEntityTemplateExecContext m_entityTemplateExecContext)
		{
			string dynValue = null;
			string filterVal = null;
			if(m_functionName == null || m_functionName == "")
			{
				dynValue = ((Tag)m_creator.TagManager.TagsInfo[m_tagIdentifier]).GetDynTagValue();
				m_replacementNode.Value = dynValue;
				if(dynValue == null)
				{
					FileWriter.Instance.WriteToFile("getdyntag returned null value");
				}
				return;
			}
			else
			{
				XmlNode root = m_entityTemplateExecContext.RunTimeXml.DocumentElement;
				if(m_substitute == null || m_substitute == "")
				{
					if(m_filter != null && m_filter != "")
					{
						string [] split = m_filter.Split(new char[] {'.'});
						XmlNode m_Node = root.SelectSingleNode(split[0]);
						if(m_Node != null)
						{
							filterVal = m_Node.InnerText;
						}
					}
				}
				else
				{
					XmlNode m_Node = root.SelectSingleNode(m_substitute);
					if(m_Node != null)
					{
						filterVal = m_Node.InnerText;
					}
				}

				Type tagType = ((Tag)m_creator.TagManager.TagsInfo[m_tagIdentifier]).GetType();
				MemberInfo methodInfo = tagType.GetMethod(m_functionName);
				if(methodInfo != null)
				{
					string returnVal = (string)tagType.InvokeMember(methodInfo.Name,
						BindingFlags.DeclaredOnly | 
						BindingFlags.Public | 
						BindingFlags.NonPublic | 
						BindingFlags.Instance | 
						BindingFlags.InvokeMethod,
						null,
						((Tag)m_creator.TagManager.TagsInfo[m_tagIdentifier]),
						new object[] {m_attributeName, m_filter, filterVal});

					XmlNode parentNode = m_replacementNode.ParentNode;

					parentNode.InnerXml = returnVal;

					m_replacementNode = parentNode.FirstChild;

					return;
				}
			}
		}

		public void ReplaceGlobal(CrmEntityTemplateExecContext m_entityTemplateExecContext)
		{
			Type tagType = typeof(Tag); //((Tag)m_creator.DbPopulator.TagManager.TagsInfo[m_tagIdentifier]).GetType();
			string filterVal = null;

			if(m_filter != null)
			{
				XmlNode root = m_entityTemplateExecContext.RunTimeXml.DocumentElement;
				if(m_substitute == null || m_substitute == "")
				{
					string [] split = m_filter.Split(new char[] {'.'});
					XmlNode m_Node = root.SelectSingleNode(split[0]);
					if(m_Node != null)
					{
						filterVal = m_Node.InnerText;
					}
				}
				else
				{
					XmlNode m_Node = root.SelectSingleNode(m_substitute);
					if(m_Node != null)
					{
						filterVal = m_Node.InnerText;
					}
				}

				
			}
			MemberInfo methodInfo = tagType.GetMethod(m_functionName);
			if(methodInfo != null)
			{
				string returnVal = (string)tagType.InvokeMember(methodInfo.Name,
					BindingFlags.DeclaredOnly | 
					BindingFlags.Public | 
					BindingFlags.NonPublic | 
					BindingFlags.Instance | 
					BindingFlags.InvokeMethod,
					null,
					((Tag)m_creator.TagManager.TagsInfo[m_tagIdentifier]),
					new object [] {m_attributeName, m_filter, filterVal});

				m_replacementNode.Value = returnVal;
			}
		}

		public void settag (string tagIdentifier, string entityName, string columnNameToSave)
		{
			m_functionName = "settag";
			m_tagIdentifier = tagIdentifier;
			m_entityName = entityName;
			m_attributeName = columnNameToSave;
		}

		public void settype(string tagIdentifier)
		{
			m_functionName = "settype";
			m_tagIdentifier = tagIdentifier;
			m_attributeName = "entityType";
		}

		public void settag_filter (string tagIdentifier, string entityName, string columnNameToSave, string filter)
		{
			m_functionName = "settag_filter";
			m_tagIdentifier = tagIdentifier;
			m_entityName = entityName;
			m_attributeName = columnNameToSave;
			m_filter = filter;
		}
	}

	public class RFData
	{
		private string m_filtername;
		private string m_filtervalue;
		private XmlNode m_replacementNode;
		private string m_pre;
		private string m_post;
		private string m_current;
		private MemberInfo m_methodInfo;
		private string [] m_functionParams;
		private XmlNode m_root;

		public XmlNode ReplacementNode
		{
			get
			{
				return m_replacementNode;
			}
			set
			{
				m_replacementNode = value;
			}
		}
		
		public string PreString
		{
			get
			{
				return m_pre;
			}
			set
			{
				m_pre = value;
			}
		}

		public string PostString
		{
			get
			{
				return m_post;
			}
			set
			{
				m_post = value;
			}
		}

		public RFData()
		{
			m_functionParams = null;
		}

		public void CreateData(XmlNode replaceNode)
		{
			string [] split = (replaceNode.InnerText).Split(new char[] {'+'});
			switch (split.Length)
			{
				case 1:
					m_pre = "";
					m_post = "";
					m_current = split[0];
					m_replacementNode = replaceNode;
					break;
				case 2:
					if(split[0].IndexOf("replace") < 0)
					{
						m_pre = split[0];
						m_current = split[1];
						m_post = "";
					}
					else
					{
						m_pre = "";
						m_current = split[0];
						m_post = split[1];
					}
					m_replacementNode = replaceNode;
					break;
				case 3:
					m_pre = split[0];
					m_current = split[1];
					m_post = split[2];
					m_replacementNode = replaceNode;
					break;
			}
			string [] functionData = (m_current.Split(new char[] {'(', ')'}));
			string [] functionInfo = functionData[1].Split(new char[] {','});
			string functionName = functionInfo[0];
			m_functionParams = new string [functionInfo.Length - 1];
			Type [] pTypes = new Type [functionInfo.Length - 1];
			for(int i = 1; i < functionInfo.Length; i++)
			{
				m_functionParams[i-1] = functionInfo[i];
				pTypes[i-1] = typeof(string);
			}

			Type mType = typeof(ReplacementFunctions);
			m_methodInfo = mType.GetMethod(functionName,pTypes);
		}

		public void Replace(ReplacementFunctions rFuncs)
		{
			if (m_filtername != null && m_filtername != "")
			{
				string[] split2 = m_filtername.Split(new char[] { '.' });
				XmlNode filternode = m_root.SelectSingleNode("//" + split2[0]);
				if (filternode != null)
				{
					m_filtervalue = filternode.InnerText;
				}

				// Added the value of the filter as the last argument
				m_functionParams[m_functionParams.Length - 1] = m_filtervalue;
							
			}

			Type mType = typeof(ReplacementFunctions);
			try
			{
				string returnString = m_pre + (string)mType.InvokeMember(m_methodInfo.Name, 
					BindingFlags.DeclaredOnly | 
					BindingFlags.Public | 
					BindingFlags.NonPublic | 
					BindingFlags.Instance | 
					BindingFlags.InvokeMethod,
					null,
					rFuncs,
					m_functionParams)
					+ m_post;
				m_replacementNode.Value = returnString;
			}
			catch (Exception e)
			{
				FileWriter.Instance.WriteToFile(string.Format("{0}\r\n{1}",e.Message,e.StackTrace));
				m_replacementNode.Value = null;
			}
		}

		public void CreateDataFiltered(XmlNode replaceNode, XmlNode root)
		{
			m_root = root;
			string[] split = (replaceNode.InnerText).Split(new char[] { '+' });
			switch (split.Length)
			{
				case 1:
					m_pre = "";
					m_post = "";
					m_current = split[0];
					m_replacementNode = replaceNode;
					break;
				case 2:
					if (split[0].IndexOf("repfiltered") < 0)
					{
						m_pre = split[0];
						m_current = split[1];
						m_post = "";
					}
					else
					{
						m_pre = "";
						m_current = split[0];
						m_post = split[1];
					}
					m_replacementNode = replaceNode;
					break;
				case 3:
					m_pre = split[0];
					m_current = split[1];
					m_post = split[2];
					m_replacementNode = replaceNode;
					break;
			}
			string[] functionData = (m_current.Split(new char[] { '(', ')' }));
			string[] functionInfo = functionData[1].Split(new char[] { ',' });

			// This will give the value of the filter. (service management, it will give the value of starttime)
			m_filtername = functionInfo[0];
			
			string functionName = functionInfo[1];
			m_functionParams = new string[functionInfo.Length - 1];
			Type[] pTypes = new Type[functionInfo.Length - 1];
			for (int i = 2; i < functionInfo.Length; i++)
			{
				m_functionParams[i - 2] = functionInfo[i];
				pTypes[i - 2] = typeof(string);
			}
			pTypes[m_functionParams.Length - 1] = typeof(string);
			Type mType = typeof(ReplacementFunctions);
			m_methodInfo = mType.GetMethod(functionName, pTypes);
		}
	}

	abstract public class CrmEntityTemplate
	{
		protected ArrayList m_childTemplateList;
		protected int m_count;
		protected XmlDocument m_entityXml;
		
		protected Type m_type;
		protected string m_entityType;
		protected bool m_settag;
		protected string m_tagIdentifier;
		protected string m_tagEntityName;
		protected string m_tagStoredType;

		protected bool m_savetype;
		protected string m_tagIdentifier2;

		protected ArrayList m_saveTagInfoList;

		public static CrmEntityTemplate GetCrmEntityTemplate (string entityType)
		{
			
			switch (entityType.ToLower())
			{
					// Supported Entities
				case "account" :
					return new CrmAccountTemplate ();
				case "annotation" :
					return new CrmAnnotationTemplate();
				case "appointment" :
					return new CrmAppointmentTemplate();
				case "businessunit" :
					return new CrmBusinessUnitTemplate();
				case "case" :
					return new CrmCaseTemplate ();
				case "campaign" :
					return new CrmCampaignTemplate ();
				case "campaignactivity" :
					return new CrmCampaignActivityTemplate ();
				case "campaignactivityitem" :
					return new CrmCampaignActivityItemTemplate ();
				case "campaignitem" :
					return new CrmCampaignItemTemplate ();
				case "campaignresponse" :
					return new CrmCampaignResponseTemplate ();
				case "constraintbasedgroup" :
					return new CrmConstraintBasedGroupTemplate();
                case "competitor" :
                    return new CrmCompetitorTemplate();
				case "contact" :
					return new CrmContactTemplate ();
				case "customeraddress" :
					return new CrmCustomerAddressTemplate ();
				case "discount" :
					return new CrmDiscountTemplate ();
				case "discounttype" :
					return new CrmDiscountTypeTemplate ();
                case "dynamicentity" :
                    return new CrmDynamicEntityTemplate();
				case "email" :
					return new CrmEmailTemplate ();
				case "equipment" :
					return new CrmEquipmentTemplate();
				case "fax" :
					return new CrmFaxTemplate ();
				case "invoice" :
					return new CrmInvoiceTemplate ();
				case "invoicedetail" :
					return new CrmInvoiceDetailTemplate ();
				case "kbarticle" :
					return new CrmKbArticleTemplate();
				case "lead" :
					return new CrmLeadTemplate ();
				case "letter" :
					return new CrmLetterTemplate ();
				case "list" :
					return new CrmListTemplate ();
				case "listmember" :
					return new CrmListMemberTemplate ();
				case "opportunity" :
					return new CrmOpportunityTemplate ();
				case "opportunityproduct" :
					return new CrmOpportunityProductTemplate ();
				case "phonecall" :
					return new CrmPhoneCallTemplate ();
				case "pricelevel" :
					return new CrmPriceLevelTemplate ();
				case "product" :
					return new CrmProductTemplate ();
				case "productpricelevel" :
					return new CrmProductPriceLevelTemplate ();
				case "quote" :
					return new CrmQuoteTemplate ();
				case "quotedetail" :
					return new CrmQuoteDetailTemplate ();
				case "resourcespec":
					return new CrmResourceSpecTemplate();
                case "systemuserrole" :
                    return new CrmSystemUserRoleTemplate();
				case "salesliterature" :
					return new CrmSalesLiteratureTemplate();
				case "salesorder" :
					return new CrmSalesOrderTemplate ();
				case "salesorderdetail" :
					return new CrmSalesOrderDetailTemplate ();
				case "service":
					return new CrmServiceTemplate();
				case "serviceappointment":
					return new CrmServiceAppointmentTemplate();
				case "subject" :
					return new CrmSubjectTemplate ();
				case "task" :
					return new CrmTaskTemplate ();
				case "systemuser" :
					return new CrmSystemUserTemplate ();
				case "uom" :
					return new CrmUoMTemplate ();
				case "uomschedule" :
					return new CrmUoMScheduleTemplate ();
				default:
					return null;
			}
		}

		public ArrayList ChildTemplateList
		{
			get
			{
				return m_childTemplateList;
			}
			set
			{
				m_childTemplateList = value;
			}
		}

		public string CrmEntityType
		{
			get
			{
				return m_entityType;
			}
		}

		public XmlDocument EntityXml
		{
			get
			{
				return m_entityXml;
			}
		}

		public string TagIdentifier
		{
			get
			{
				return m_tagIdentifier;
			}
		}

		public string TagIdentifier2
		{
			get
			{
				return m_tagIdentifier2;
			}
		}

		public string TagStoredType
		{
			get
			{
				return m_tagStoredType;
			}
		}

		public string TagEntityName
		{
			get
			{
				return m_tagEntityName;
			}
		}

		public bool SetTag
		{
			get
			{
				return m_settag;
			}
		}

		public int Count
		{
			get
			{
				return m_count;
			}
			set
			{
				m_count = value;
			}
		}

		public Type EntityType
		{
			get
			{
				return m_type;
			}
		}

		public bool SaveType
		{
			get
			{
				return m_savetype;
			}
		}

		public ArrayList SaveTagInfoList
		{
			get
			{
				return m_saveTagInfoList;
			}
			set
			{
				m_saveTagInfoList = value;
			}
		}


		public CrmEntityTemplate()
		{
			m_childTemplateList = new ArrayList();
			m_saveTagInfoList = new ArrayList();
			m_entityXml = new XmlDocument ();
			m_settag = false;
			m_savetype = false;
		}

		public abstract BusinessEntity GetBusinessEntity();

		public virtual string CreateEntity (XmlDocument instanceXML, CrmService webService, BusinessEntity m_entity, DbPopulator dbPopulator )
		{
            bool quiet = dbPopulator.QuietMode;
			for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
			{
				XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
				if (n.InnerXml != "") 
				{
					try
					{
						AddAttribute(n.Name, ref m_entity, n.InnerXml);
					}
					catch (Exception e)
					{
						string err = string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), e.Message);
						err = err + "Skipping entering the value of the parameter\r\n";
						err = err + e.ToString();
						FileWriter.Instance.WriteToFile(err);
					}
				}
			}

			try
			{
				string entityId = webService.Create (m_entity).ToString();
				if(!quiet)
					Console.WriteLine("{0} with id = {1} created", m_type.Name, entityId);
				return entityId;
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
		}

		public virtual void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
            // Update the newly created entity with custom attributes.
            XmlNodeList propertyList = instanceXML.DocumentElement.SelectNodes("//property");
            if (propertyList != null && propertyList.Count != 0)
            {
                DynamicEntity dynUser = new DynamicEntity();
                dynUser.Name = m_entityType;
                dynUser.Properties = new Property[propertyList.Count];
                for (int j = 0; j < propertyList.Count; j++)
                {
                    XmlNode child = propertyList[j];
                    switch (child.Attributes["type"].Value)
                    {
                        case "string":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateStringProperty(child.Attributes["name"].Value, child.Attributes["value"].Value);
                            break;
                        case "owner":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateOwnerProperty(child.Attributes["name"].Value, CrmTypes.CreateOwner(EntityName.systemuser.ToString(), new Guid(child.Attributes["value"].Value)));
                            break;
                        case "picklist":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreatePicklistProperty(child.Attributes["name"].Value, CrmTypes.CreatePicklist(int.Parse(child.Attributes["value"].Value)));
                            break;                        
                        case "money":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmMoneyProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmMoney(decimal.Parse(child.Attributes["value"].Value)));
                            break;
                        case "boolean":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmBooleanProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmBoolean(bool.Parse(child.Attributes["value"].Value)));
                            break;
                        case "decimal":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmDecimalProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmDecimal(decimal.Parse(child.Attributes["value"].Value)));
                            break;
                        case "datetime":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmDateTimeProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmDateTime(child.Attributes["value"].Value));
                            break;
                        case "float":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmFloatProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmFloat(float.Parse(child.Attributes["value"].Value)));
                            break;
                        case "lookup":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateLookupProperty(child.Attributes["name"].Value, CrmTypes.CreateLookup(EntityName.account.ToString(), new Guid(child.Attributes["value"].Value)));
                            break;
                        case "key":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateKeyProperty(child.Attributes["name"].Value, new Key(new Guid(entityId)));
                            break;
                        case "int":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmNumberProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmNumber(int.Parse(child.Attributes["value"].Value)));
                            break;
                        case "number":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmNumberProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmNumber(int.Parse(child.Attributes["value"].Value)));
                            break;
                        default:
                            Console.WriteLine(child.Attributes["type"].Value + " is not implemented yet. Needs to be implemented to generate Property");
                            break;
                    }
                }

                
                TargetUpdateDynamic tud = new TargetUpdateDynamic();
                tud.Entity = dynUser;
                UpdateRequest updateRequest = new UpdateRequest();
                updateRequest.Target = tud;
                try
                {
                    webService.Execute(updateRequest);
                    if (!quiet)
                    {
                        Console.WriteLine("User with id = {0} updated with dynamic Attributes", entityId);
                    }
                }
                catch (System.Web.Services.Protocols.SoapException ex)
                {
                    string err = string.Format("{0}\r\n", ex.ToString());
                    err = err + string.Format("Soap Exception Detail: {0}\r\n", ex.Detail.InnerXml);
                    err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
                    FileWriter.Instance.WriteToFile(err);
                }
                catch (Exception ex)
                {
                    string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
                        Thread.CurrentThread.GetHashCode());
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
                    err = err + ex.ToString();
                    FileWriter.Instance.WriteToFile(err);
                }
            }
		}

		protected object GetTypedValue (string typeName, string stringVal)
		{
			switch (typeName.ToLower())
			{
				case "decimal" :
					return Decimal.Parse (stringVal);
				case "int32" :
					return Int32.Parse (stringVal);
				case "string" :
					return stringVal;
				case "guid" :
					return new Guid (stringVal);
				case "double" :
					return Double.Parse (stringVal);
				case "datetime":
					return DateTime.Parse (stringVal);
				case "boolean" :
					return Boolean.Parse (stringVal);
				case "owner" :
					Owner ownerid = new Owner();
					ownerid.Value = new Guid(stringVal);
					ownerid.type = EntityName.systemuser.ToString();
					return ownerid;	
				case "crmboolean" :
					CrmBoolean boolean = new CrmBoolean();
					boolean.Value = (int.Parse(stringVal) != 0);
					return boolean;
				case "crmnumber" :
					CrmNumber number = new CrmNumber();
					number.Value = Int32.Parse(stringVal);
					return number;
				case "picklist" :
					Picklist picklist = new Picklist(); 
					picklist.Value = int.Parse(stringVal);
					return picklist;
				case "crmfloat" :
					CrmFloat crmFloat = new CrmFloat ();
					crmFloat.Value = Single.Parse(stringVal);
					return crmFloat;
				case "crmmoney" :
					CrmMoney crmMoney = new CrmMoney ();
					crmMoney.Value = decimal.Parse(stringVal);
					return crmMoney;
				case "crmdatetime" :
					CrmDateTime crmDateTime = new CrmDateTime ();
					crmDateTime.Value = stringVal;
					return crmDateTime;
				case "lookup" :
					Lookup lookup = new Lookup();
					lookup.Value = new Guid(stringVal);
					return lookup;
				case "status" :
					Status status = new Status();
					status.Value = int.Parse(stringVal);
					return status;
				case "incidentstate" :
					IncidentState incidentState = new IncidentState();
					Type stateType = typeof(IncidentState);
					FieldInfo fi = stateType.GetField(stringVal);
					if(fi != null)
					{
						return fi.GetValue(incidentState);
					}
					else
						return null;
				case "incidentstateinfo" :
					IncidentStateInfo incidentStateInfo = new IncidentStateInfo();
					Type stateInfoType = typeof(IncidentStateInfo);
					PropertyInfo incidentfi = stateInfoType.GetProperty(stringVal);
					if(incidentfi != null)
					{
						return incidentfi.GetValue(incidentStateInfo,null);
					}
					else
						return null;
				case "quotestate" :
					QuoteState quoteState = new QuoteState();
					Type quoteStateType = typeof(QuoteState);
					FieldInfo quoteFi = quoteStateType.GetField(stringVal);
					if(quoteFi != null)
					{
						return quoteFi.GetValue(quoteState);
					}
					else
						return null;
				
				case "quoteclosestate" :
					QuoteCloseState quoteCloseState = new QuoteCloseState();
					Type quoteCloseStateType = typeof(QuoteCloseState);
					FieldInfo quoteCloseFi = quoteCloseStateType.GetField(stringVal);
					if(quoteCloseFi != null)
					{
						return quoteCloseFi.GetValue(quoteCloseState);
					}
					else
						return null;
				case "salesorderstate" :
					SalesOrderState salesOrderState = new SalesOrderState();
					Type salesOrderStateType = typeof(SalesOrderState);
					FieldInfo salesOrderFi = salesOrderStateType.GetField(stringVal);
					if(salesOrderFi != null)
					{
						return salesOrderFi.GetValue(salesOrderState);
					}
					else
					{
						return null;
					}
				
				case "invoicestate" :
					InvoiceState invoiceState = new InvoiceState();
					Type invoiceStateType = typeof(InvoiceState);
					FieldInfo invoiceFi = invoiceStateType.GetField(stringVal);
					if(invoiceFi != null)
					{
						return invoiceFi.GetValue(invoiceState);
					}
					else
					{
						return null;
					}
				
				case "opportunitystate" :
					OpportunityState opportunityState = new OpportunityState();
					Type opportunityStateType = typeof(OpportunityState);
					FieldInfo opportunityFi = opportunityStateType.GetField(stringVal);
					if(opportunityFi != null)
					{
						return opportunityFi.GetValue(opportunityState);
					}
					else
					{
						return null;
					}
				case "crmdecimal" :
					CrmDecimal crmDecimal = new CrmDecimal();
					crmDecimal.Value = decimal.Parse(stringVal);
					return crmDecimal;
				case "activityparty[]" :

					string[] split = null;
					activityparty[] activityPartyList = null;
					if (stringVal.StartsWith("[") && stringVal.EndsWith("]"))
					{
						string parties = stringVal.Substring (1, stringVal.Length - 2);
						split = parties.Split(new char[] { ';' });
						activityPartyList = new activityparty[split.Length];
						for (int i = 0; i < split.Length; i++)
						{
							string[] participant = split[i].Split(new char[] { ',' });
							if (participant.Length != 2)
							{
								throw new ArgumentException("Invalid activitypartylist");
							}

							activityPartyList[i] = new activityparty();
							activityPartyList[i].partyid = new Lookup();
							activityPartyList[i].partyid.Value = new Guid(participant[0]);
							activityPartyList[i].partyid.type = participant[1];
						}
					}
					else
					{
						split = stringVal.Split(new char[] { ',' });
						activityPartyList = new activityparty[split.Length];
						for (int i = 0; i < split.Length; i++)
						{
							activityPartyList[i] = new activityparty();
							(activityPartyList[i]).partyid = new Lookup();
							(activityPartyList[i]).partyid.Value = new Guid(stringVal);
							activityPartyList[i].partyid.type = EntityName.systemuser.ToString();
						}
					}
					return activityPartyList;
				case "entitynamereference" :
					EntityNameReference entityNameReference = new EntityNameReference();
					entityNameReference.Value = stringVal;
					return entityNameReference;

				case "uniqueidentifier" :
					UniqueIdentifier uniqueIdentifier = new UniqueIdentifier();
					uniqueIdentifier.Value = new Guid(stringVal);
					return uniqueIdentifier;
				case "taskstate" :
					TaskState taskState = new TaskState();
					Type taskStateType = typeof(TaskState);
					FieldInfo taskFi = taskStateType.GetField(stringVal);
					if(taskFi != null)
					{
						return taskFi.GetValue(taskState);
					}
					else
					{
						return null;
					}
				case "taskstateinfo" :
					TaskStateInfo taskStateInfo = new TaskStateInfo();
					Type taskStateInfoType = typeof(TaskStateInfo);
					PropertyInfo taskInfoFi = taskStateInfoType.GetProperty(stringVal);
					if(taskInfoFi != null)
					{
						return taskInfoFi.GetValue(taskStateInfo,null);
					}
					else
					{
						return null;
					}
				case "appointmentstateinfo" :
					AppointmentStateInfo apptStateInfo = new AppointmentStateInfo();
					Type apptStateInfoType = typeof(AppointmentStateInfo);
					PropertyInfo apptInfoFi = apptStateInfoType.GetProperty(stringVal);
					if(apptInfoFi != null)
					{
						return apptInfoFi.GetValue(apptStateInfo,null);
					}
					else
					{
						return null;
					}
				case "phonecallstateinfo" :
					PhoneCallStateInfo phonecallStateInfo = new PhoneCallStateInfo();
					Type phonecallStateInfoType = typeof(PhoneCallStateInfo);
					PropertyInfo phonecallInfoFi = phonecallStateInfoType.GetProperty(stringVal);
					if(phonecallInfoFi != null)
					{
						return phonecallInfoFi.GetValue(phonecallStateInfo,null);
					}
					else
					{
						return null;
					}
				case "letterstateinfo" :
					LetterStateInfo letterStateInfo = new LetterStateInfo();
					Type letterStateInfoType = typeof(LetterStateInfo);
					PropertyInfo letterInfoFi = letterStateInfoType.GetProperty(stringVal);
					if(letterInfoFi != null)
					{
						return letterInfoFi.GetValue(letterStateInfo,null);
					}
					else
					{
						return null;
					}
				case "faxstateinfo" :
					FaxStateInfo faxStateInfo = new FaxStateInfo();
					Type faxStateInfoType = typeof(FaxStateInfo);
					PropertyInfo faxInfoFi = faxStateInfoType.GetProperty(stringVal);
					if(faxInfoFi != null)
					{
						return faxInfoFi.GetValue(faxStateInfo,null);
					}
					else
					{
						return null;
					}
				case "emailstateinfo" :
					EmailStateInfo emailStateInfo = new EmailStateInfo();
					Type emailStateInfoType = typeof(EmailStateInfo);
					PropertyInfo emailInfoFi = emailStateInfoType.GetProperty(stringVal);
					if(emailInfoFi != null)
					{
						return emailInfoFi.GetValue(emailStateInfo,null);
					}
					else
					{
						return null;
					}
				case "opportunitystateinfo":
					OpportunityStateInfo oppStateInfo = new OpportunityStateInfo();
					Type oppStateInfoType = typeof(OpportunityStateInfo);
					PropertyInfo oppStateInfoFi = oppStateInfoType.GetProperty(stringVal);
					if(oppStateInfoFi != null)
						return oppStateInfoFi.GetValue(oppStateInfo,null);
					else
						return null;
				case "invoicestateinfo" :
					InvoiceStateInfo invoiceStateInfo = new InvoiceStateInfo();
					Type invoiceStateInfoType = typeof(InvoiceStateInfo);
					PropertyInfo invoiceInfoFi = invoiceStateInfoType.GetProperty(stringVal);
					if(invoiceInfoFi != null)
					{
						return invoiceInfoFi.GetValue(invoiceStateInfo,null);
					}
					else
					{
						return null;
					}
				case "salesorderstateinfo" :
					SalesOrderStateInfo salesOrderStateInfo = new SalesOrderStateInfo();
					Type salesOrderStateInfoType = typeof(SalesOrderStateInfo);
					PropertyInfo salesOrderInfoFi = salesOrderStateInfoType.GetProperty(stringVal);
					if(salesOrderInfoFi != null)
					{
						return salesOrderInfoFi.GetValue(salesOrderStateInfo,null);
					}
					else
					{
						return null;
					}
				case "quotestateinfo" :
					QuoteStateInfo quoteStateInfo = new QuoteStateInfo();
					Type quoteStateInfoType = typeof(QuoteStateInfo);
					PropertyInfo quoteInfoFi = quoteStateInfoType.GetProperty(stringVal);
					if(quoteInfoFi != null)
					{
						return quoteInfoFi.GetValue(quoteStateInfo,null);
					}
					else
						return null;
				default :
					FileWriter.Instance.WriteToFile (string.Format("Property Type \"{0}\" was not found", typeName));
					return null;
			}
		}

		protected object GetInstance(string parameter)
		{
			switch (parameter.ToLower())
			{
				case "customer" :
					Customer customer = new Customer ();
					return customer;
				case "status" :
					Status status = new Status();
					return status;
				case "lookup" :
					Lookup lookup = new Lookup();
					return lookup;
				case "crmdatetime" :
					CrmDateTime crmDateTime = new CrmDateTime ();
					return crmDateTime;
				case "crmmoney" :
					CrmMoney crmMoney = new CrmMoney ();
					return crmMoney;
				case "owner" :
					Owner ownerid = new Owner();
					return ownerid;	
				case "crmboolean" :
					CrmBoolean boolean = new CrmBoolean();
					return boolean;
				case "crmnumber" :
					CrmNumber number = new CrmNumber();
					return number;
				case "picklist" :
					Picklist picklist = new Picklist();
					return picklist;
				case "crmfloat" :
					CrmFloat crmFloat = new CrmFloat ();
					return crmFloat;
				case "uniqueidentifier" :
					UniqueIdentifier uniqueIdentifier = new UniqueIdentifier();
					return uniqueIdentifier;
				default :
					FileWriter.Instance.WriteToFile(string.Format("Property Type \"{0}\" not found"));
					return null;
			}
		}

		protected void AddAttribute (string attributeName, ref BusinessEntity a, string objVal)
		{
			string [] parameters = attributeName.Split(new char[] {'.'},2);

			PropertyInfo fi = m_type.GetProperty(parameters[0]);
            if (fi != null)
            {
                if (parameters.Length > 1)
                {
                    object macroObject = null;
                    if ((macroObject = fi.GetValue(a, null)) == null)
                        macroObject = GetInstance(fi.PropertyType.Name);
                    AddSubAttribute(parameters[1], ref macroObject, objVal);
                    fi.SetValue(a, macroObject, null);
                }
                else
                {
                    object typedValue = GetTypedValue(fi.PropertyType.Name, objVal);
                    fi.SetValue(a, typedValue, null);
                }
            }
            else if (attributeName != "role" && attributeName != "PUID" && attributeName != "passportuser") 
            {
                FileWriter.Instance.WriteToFile(string.Format(" The attribute name \"{0}\" specified is not a valid property name for {1}", attributeName, m_type.Name));
            }
		}

		protected void AddSubAttribute (string attributeName, ref object a, string objVal)
		{
			string [] parameters = attributeName.Split(new char[] {'.'},2);
			
			Type thisType = a.GetType();
			PropertyInfo fi = thisType.GetProperty (parameters[0]);
			if (fi != null)
			{
				if(parameters.Length > 1)
				{
					object macroObject = null;
					if((macroObject = fi.GetValue(a,null)) == null)
						macroObject = GetInstance (fi.PropertyType.Name);
					
					AddSubAttribute(parameters[1],ref macroObject,objVal);
				}
				else
				{
					object typedValue = GetTypedValue(fi.PropertyType.Name,objVal);
					fi.SetValue(a,typedValue,null);
				}
			}
			else
			{
				FileWriter.Instance.WriteToFile (string.Format(" The attribute name \"{0}\" specified is not a valid property name for {1}", attributeName, m_type.Name)); 
			}
		}

		public void ProcessExplicitElements(XmlAttributeCollection elements)
		{
			for (int i = 0; i < elements.Count; i++)
			{
				// MetaAttributes are attributes not specifying element values for the entity, such as "count"
				if (ProcessMetaAttribute (elements[i]))
				{
					continue;
				}
				if (ProcessSaveAttribute (elements[i]))
				{
					continue;
				}

				XmlNode element = m_entityXml.SelectSingleNode ("//" + elements[i].Name);
				if (element != null)
				{
					XmlNode text = element.SelectSingleNode ("child::text()");
					if (text != null)
					{
						text.Value = elements[i].Value;
					}
					else
					{
						element.AppendChild (m_entityXml.CreateTextNode (elements[i].Value));
					}
				}
				else
				{
                    if (elements[i].Value.Contains("addproperty"))
                    {
                        string [] split = elements[i].Value.Split(new char[] { '(', ',', ')' },3);

                        XmlElement newEl = m_entityXml.CreateElement("property");
                        newEl.SetAttribute("name", elements[i].Name);
                        newEl.SetAttribute("type", split[1]);
                        newEl.SetAttribute("value", split[2]); 
                        m_entityXml.DocumentElement.AppendChild(newEl);
                    }
                    else
                    {
                        XmlElement newEl = m_entityXml.CreateElement(elements[i].Name);
                        newEl.AppendChild(m_entityXml.CreateTextNode(elements[i].Value));
                        m_entityXml.DocumentElement.AppendChild(newEl);
                    }
				}
			}
		}

		public virtual bool ProcessSaveAttribute (XmlAttribute att)
		{
			string attName = att.Name.ToLower();
			if(attName.IndexOf("save_",0) >= 0)
			{
				string attType = attName.Substring(5);
				string [] split = (att.Value).Split(new char [] {'(', ')'});
				string functionName = split[0];
				string [] functionArgs = (split[1]).Split(new char [] {','});

				TagNodeData m_tagNode = new TagNodeData(null);
				Type tagType = typeof(TagNodeData);
				MemberInfo methodInfo = tagType.GetMethod(functionName);
				if(methodInfo != null)
				{
					tagType.InvokeMember(methodInfo.Name,
						BindingFlags.DeclaredOnly |
						BindingFlags.Public |
						BindingFlags.NonPublic |
						BindingFlags.Instance |
						BindingFlags.InvokeMethod,
						null,
						m_tagNode,
						functionArgs);
				}
				m_saveTagInfoList.Add(m_tagNode);
				return true;
			}
			else
				return false;
		}

		public virtual bool ProcessMetaAttribute (XmlAttribute att)
		{
			if(att.Name.ToLower() == "count")
			{
				m_count = int.Parse(att.Value);
				return true;;
			}				
			else
			{
				return false;
			}			
		}
	}
    
	public class CrmAccountTemplate : CrmEntityTemplate
	{

		public CrmAccountTemplate ()
		{            
			m_entityXml.LoadXml (m_entityXmlString);
            account m_entity = new account();                
            m_type = m_entity.GetType();
            m_entityType = EntityName.account.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new account();
		}

		private static string m_entityXmlString =
            @"<account>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<name>replace(randomname)</name>
    			<telephone1>replace(randomphone)</telephone1>
    			<telephone2>replace(randomphone)</telephone2>
    			<websiteurl>replace(randomurl)</websiteurl>
    			<emailaddress1>replace(randomemail)</emailaddress1>
    			<numberofemployees>replace(randomnumber)</numberofemployees>
    			<description>replace(randomdescription,5)</description>
    			<industrycode></industrycode>
    			<customertypecode></customertypecode>
    			<accountcategorycode ></accountcategorycode>
    			<territorycode ></territorycode>
    			<accountratingcode ></accountratingcode>
    			<preferredcontactmethodcode >1</preferredcontactmethodcode>
    			<ownershipcode></ownershipcode>
				<creditonhold>0</creditonhold>
    			<donotemail>0</donotemail>
    			<donotphone>0</donotphone>
    			<ownershipcode></ownershipcode>
    			<donotfax>0</donotfax>
    			<donotpostalmail>0</donotpostalmail>
                <address1_line1>replace(randomaddressline1)</address1_line1>
                <address1_city>replace(randomcity)</address1_city>
                <address1_stateorprovince>replace(randomstate)</address1_stateorprovince>
                <address1_country>replace(randomcountry)</address1_country>
                <address1_postalcode>replace(randomnumber,10000,99999)</address1_postalcode>
                <address1_telephone1>replace(randomphone)</address1_telephone1>
                <address1_name>First Account Address</address1_name>
    		</account>";
	};

	public class CrmAnnotationTemplate : CrmEntityTemplate
	{
		public CrmAnnotationTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			annotation m_entity = new annotation();
			m_type = m_entity.GetType();
			m_entityType = EntityName.annotation.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new annotation();
		}

		private static string m_entityXmlString =
			@"<annotation>
    			<isdocument>0</isdocument>
    			<objecttypecode></objecttypecode>
    			<subject>replace(randomsubject)</subject>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<notetext>replace(randomtext,1)</notetext>
    		</annotation>";
	};

	public class CrmAppointmentTemplate : CrmEntityTemplate
	{
		public CrmAppointmentTemplate ()
		{
			try
			{
				m_entityXml.LoadXml (m_entityXmlString);
			}
			catch(Exception e)
			{
				Console.WriteLine(e.Message);
			}
			appointment m_entity = new appointment();
			m_type = m_entity.GetType();
			m_entityType = EntityName.appointment.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new appointment();
		}

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{
				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "cancel")
						{
							SetStateAppointmentRequest setStateAppointmentReq = new SetStateAppointmentRequest();
							setStateAppointmentReq.EntityId = new Guid(entityId);
							setStateAppointmentReq.AppointmentState = AppointmentState.Canceled;
							setStateAppointmentReq.AppointmentStatus = -1;
							webService.Execute(setStateAppointmentReq);
							if(!quiet)
								Console.WriteLine("Appointment with id = {0} updated successfully to cancel state", entityId);
						}
						else if(n.InnerText.ToLower() == "complete")
						{
							SetStateAppointmentRequest setStateAppointmentReq = new SetStateAppointmentRequest();
							setStateAppointmentReq.EntityId = new Guid(entityId);
							setStateAppointmentReq.AppointmentState = AppointmentState.Completed;
							setStateAppointmentReq.AppointmentStatus = -1;
							webService.Execute(setStateAppointmentReq);
							if(!quiet)
								Console.WriteLine("Appointment with id = {0} updated successfully to complete state", entityId);
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}

		}

		private static string m_entityXmlString =
			@"<appointment>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<description>replace(randomdescription,3)</description>
    			<requiredattendees></requiredattendees>
    			<organizer>replace(owneridreplace)</organizer>
    			<subcategory>replace(randomstring)</subcategory>
    			<prioritycode>1</prioritycode>
    			<scheduleddurationminutes>30</scheduleddurationminutes>
    			<scheduledstart>replace(randomtime)</scheduledstart>
    			<subject>replace(randomsubject)</subject>
    			<regardingobjectid></regardingobjectid>
    		</appointment>";
	};

	public class CrmBusinessUnitTemplate : CrmEntityTemplate
	{
		public CrmBusinessUnitTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			businessunit m_entity = new businessunit();
			m_type = m_entity.GetType();
			m_entityType = EntityName.businessunit.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new businessunit();
		}

		private static string m_entityXmlString =
			@"<businessunit>
    			<name>replace(randomname)</name>
				<parentbusinessunitid></parentbusinessunitid>
				<emailaddress>replace(randomemail)</emailaddress>
    		</businessunit>";
	}

	public class CrmCampaignTemplate : CrmEntityTemplate
	{
		public CrmCampaignTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			campaign m_entity = new campaign();
			m_type = m_entity.GetType();
			m_entityType = EntityName.campaign.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new campaign();
		}

		private static string m_entityXmlString =
			@"<campaign>
    			<name>replace(randomcampaign)</name>
				<ownerid>replace(owneridreplace)</ownerid>
    			<statuscode>1</statuscode>
				<expectedresponse>100</expectedresponse>
				<description>replace(randomdescription,5)</description>
				<createdon>replace(randomdate,-60.0)</createdon>
				<modifiedon>replace(randomdate,-30.0)</modifiedon>			
    		</campaign>";
	}

	public class CrmCampaignActivityTemplate : CrmEntityTemplate
	{
		public CrmCampaignActivityTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			campaignactivity m_entity = new campaignactivity();
			m_type = m_entity.GetType();
			m_entityType = EntityName.campaignactivity.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new campaignactivity();
		}

		private static string m_entityXmlString =
			@"<campaignactivity>
    			<regardingobjectid></regardingobjectid>
				<ownerid>replace(owneridreplace)</ownerid>
    			<subject>replace(randomsubject)</subject>
				<description>replace(randomdescription)</description>
				<channeltypecode>replace(randomnumber,1,3)</channeltypecode>
    		</campaignactivity>";
	}

	public class CrmCampaignItemTemplate : CrmEntityTemplate
	{
		public CrmCampaignItemTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			campaignitem m_entity = new campaignitem();
			m_type = m_entity.GetType();
			m_entityType = EntityName.campaign.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new campaignitem();
		}

		public override string CreateEntity (XmlDocument instanceXML, CrmService webService, BusinessEntity m_entity, DbPopulator dbPopulator)
        {
            bool quiet = dbPopulator.QuietMode;
			for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
			{
				XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
				if (n.InnerText != "") 
				{
					try
					{
						if(n.Name.ToLower() != "entityname")
							AddAttribute ( n.Name, ref m_entity, n.InnerText);
					}
					catch (Exception e)
					{
						string err = string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), e.Message);
						err = err + "Skipping entering the value of the parameter\r\n";
						err = err + e.ToString();
						FileWriter.Instance.WriteToFile(err);
					}
				}
			}

			AddItemCampaignRequest addItemCampaignRequest = new AddItemCampaignRequest();
			addItemCampaignRequest.EntityId = ((campaignitem)m_entity).entityid.Value;                //new Guid(instanceXML.SelectSingleNode("entityid").InnerText); 
			addItemCampaignRequest.CampaignId = ((campaignitem)m_entity).campaignid.Value; 
			XmlNode a = instanceXML.DocumentElement.SelectSingleNode("entityname");                   //new Guid(instanceXML.SelectSingleNode("campaignid").InnerText);
			addItemCampaignRequest.EntityName = (EntityName)Enum.Parse(typeof(EntityName), a.InnerText,true);
			
			try
			{
	
				Microsoft.Crm.Sdk.Proxy.Response response = webService.Execute(addItemCampaignRequest);
				AddItemCampaignResponse addItemCampaignResponse = response as AddItemCampaignResponse;
				
				string entityId = addItemCampaignResponse.CampaignItemId.ToString();
				if(!quiet)
					Console.WriteLine("Campaign Item with id = {0} created", entityId);
				return entityId;
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail:" + ex.Detail.InnerXml);
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
		}

		private static string m_entityXmlString =
			@"<campaignitem>
    			<campaignid></campaignid>
				<entityid></entityid>
    			<entityname></entityname>
    		</campaignitem>";
	}

	public class CrmCampaignActivityItemTemplate : CrmEntityTemplate
	{
		public CrmCampaignActivityItemTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			campaignactivityitem m_entity = new campaignactivityitem();
			m_type = m_entity.GetType();
			m_entityType = EntityName.campaignactivityitem.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new campaignactivityitem();
		}

		public override string CreateEntity (XmlDocument instanceXML, CrmService webService, BusinessEntity m_entity, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
			{
				XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
				if (n.InnerText != "") 
				{
					try
					{
						if(n.Name.ToLower() != "entityname")
							AddAttribute ( n.Name, ref m_entity, n.InnerText);
					}			
					catch (Exception e)
					{
						string err = string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), e.Message);
						err = err + "Skipping entering the value of the parameter\r\n";
						err = err + e.ToString();
						FileWriter.Instance.WriteToFile(err);
					}
				}
			}

			AddItemCampaignActivityRequest addItemCampaignActivityRequest = new AddItemCampaignActivityRequest();

			addItemCampaignActivityRequest.CampaignActivityId = ((campaignactivityitem)m_entity).campaignactivityid.Value;
			
			XmlNode a = instanceXML.DocumentElement.SelectSingleNode("entityname"); 
			addItemCampaignActivityRequest.EntityName = (EntityName)Enum.Parse(typeof(EntityName), a.InnerText,true);
			
			addItemCampaignActivityRequest.ItemId = ((campaignactivityitem)m_entity).itemid.Value;
							
			try
			{
				Microsoft.Crm.Sdk.Proxy.Response response = webService.Execute(addItemCampaignActivityRequest);
				AddItemCampaignActivityResponse addItemCampaignActivityResponse = response as AddItemCampaignActivityResponse;
				
				string entityId = addItemCampaignActivityResponse.CampaignActivityItemId.ToString();
				if(!quiet)
					Console.WriteLine("CampaignActivityItem with id = {0} created", entityId);
				return entityId;
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail:" + ex.Detail.InnerXml);
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
		}

		private static string m_entityXmlString =
			@"<campaignactivityitem>
    			<campaignactivityid></campaignactivityid>
				<itemid></itemid>
    			<entityname></entityname>
    		</campaignactivityitem>";
	}

	public class CrmCampaignResponseTemplate : CrmEntityTemplate
	{
		public CrmCampaignResponseTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			campaignresponse m_entity = new campaignresponse();
			m_type = m_entity.GetType();
			m_entityType = EntityName.campaignresponse.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new campaignresponse();
		}

		private static string m_entityXmlString =
			@"<campaignresponse>
    			<regardingobjectid></regardingobjectid>
				<ownerid>replace(owneridreplace)</ownerid>
    			<subject>replace(randomsubject)</subject>
				<description>replace(randomdescription,5)</description>
				<responsecode>1</responsecode>
    		</campaignresponse>";
	}

	public class CrmCaseTemplate : CrmEntityTemplate
	{
		public CrmCaseTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			incident m_entity = new incident();
			m_type = m_entity.GetType();
			m_entityType = EntityName.incident.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new incident();
		}

		private static string m_entityXmlString =
			@"<incident>
    			<title>replace(randomsubject)</title>
    			<casetypecode>replace(randomnumber,1,3)</casetypecode>
    			<caseorigincode>replace(randomnumber,1,3)</caseorigincode>
    			<customersatisfactioncode>replace(randomnumber,1,5)</customersatisfactioncode>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<statuscode>1</statuscode>
				<statecode>Active</statecode>
    			<prioritycode>replace(randomnumber,1,3)</prioritycode>
    			<followupby>replace(randomtime)</followupby>
    			<productid></productid>
    		</incident>";
	}

	public class CrmCustomerAddressTemplate : CrmEntityTemplate
	{
		public CrmCustomerAddressTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			customeraddress m_entity = new customeraddress();
			m_type = m_entity.GetType();
			m_entityType = EntityName.customeraddress.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new customeraddress();
		}

		private static string m_entityXmlString =
            @"<customeraddress>
    			<parentid></parentid>
    			<objecttypecode></objecttypecode>
    			<name>Customer Address + replace(getnextnumber)</name>
    			<line1>replace(randomaddressline1)</line1>
				<line2></line2>
				<line3></line3>
    			<city>replace(randomcity)</city>
                <country>replace(randomcountry)</country>
                <stateorprovince>replace(randomstate)</stateorprovince>
    			<stateorprovince>replace(randomstate)</stateorprovince>
    			<postalcode>replace(randomnumber,10000,99999)</postalcode>
    			<telephone1>replace(randomphone)</telephone1>
    			<fax>replace(randomphone)</fax>
    		</customeraddress>";
	}

	public class CrmConstraintBasedGroupTemplate : CrmEntityTemplate
	{
		public CrmConstraintBasedGroupTemplate()
		{
			m_entityXml.LoadXml(m_entityXmlString);
			constraintbasedgroup m_entity = new constraintbasedgroup();
			m_type = m_entity.GetType();
			m_entityType = EntityName.constraintbasedgroup.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new constraintbasedgroup();
		}

		private static string m_entityXmlString =
			@"<constraintbasedgroup>
				<name>replace(randomname)</name>
				<grouptypecode>0</grouptypecode>
			  </constraintbasedgroup>";
	};

    public class CrmCompetitorTemplate : CrmEntityTemplate
    {

        public CrmCompetitorTemplate()
        {
            m_entityXml.LoadXml(m_entityXmlString);
            competitor m_entity = new competitor();            
            m_type = m_entity.GetType();
            m_entityType = EntityName.competitor.ToString();
        }

        public override BusinessEntity GetBusinessEntity()
        {
            return new competitor();
        }

        private static string m_entityXmlString =
            @"<competitor>
    			<name>replace(randomfirstname)</name>    			
    		</competitor>";
    };

	public class CrmContactTemplate : CrmEntityTemplate
	{

		public CrmContactTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			contact m_entity = new contact();              
			m_type = m_entity.GetType();
			m_entityType = EntityName.contact.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new contact();
		}

		private static string m_entityXmlString =
            @"<contact>
    			<firstname>replace(randomfirstname)</firstname>
    			<middlename></middlename>
    			<lastname>replace(randomlastname)</lastname>
    			<jobtitle>replace(randomjobtitle)</jobtitle>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<creditonhold>0</creditonhold>
    			<preferredcontactmethodcode>1</preferredcontactmethodcode>
    			<emailaddress1>replace(randomemail)</emailaddress1>
    			<donotemail>0</donotemail>
    			<donotphone>0</donotphone>
    			<donotfax>0</donotfax>
    			<donotpostalmail>0</donotpostalmail>
                <mobilephone>replace(randomphone)</mobilephone>
                <telephone1>replace(randomphone)</telephone1>
                <telephone2>replace(randomphone)</telephone2>
                <fax>replace(randomphone)</fax>
                <address1_line1>replace(randomaddressline1)</address1_line1>
                <address1_city>replace(randomcity)</address1_city>
                <address1_stateorprovince>replace(randomstate)</address1_stateorprovince>
                <address1_country>replace(randomcountry)</address1_country>
                <address1_postalcode>replace(randomnumber,10000,99999)</address1_postalcode>
                <address1_telephone1>replace(randomphone)</address1_telephone1>
                <address1_name>First Contact Address</address1_name>
    		</contact>";
	};

	public class CrmDiscountTemplate : CrmEntityTemplate
	{
		public CrmDiscountTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			discount m_entity = new discount();
			m_type = m_entity.GetType();
			m_entityType = EntityName.discount.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new discount();
		}

		private static string m_entityXmlString =
			@"<discount>
    			<discounttypeid></discounttypeid>
    			<lowquantity></lowquantity>
    			<highquantity></highquantity>
    			<percentage>replace(randomnumber,5,10)</percentage>
    		</discount>";
	};

	public class CrmDiscountTypeTemplate : CrmEntityTemplate
	{
		public CrmDiscountTypeTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			discounttype m_entity = new discounttype ();
			m_type = m_entity.GetType();
			m_entityType = EntityName.discounttype.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new discounttype();
		}

		private static string m_entityXmlString =
			@"<discounttype>
    			<name>replace(randomdiscountlist)</name>
    			<isamounttype>0</isamounttype>
    		</discounttype>";
	};

    public class CrmDynamicEntityTemplate : CrmEntityTemplate
    {
        public CrmDynamicEntityTemplate()
        {
            m_entityXml.LoadXml(m_entityXmlString);
            DynamicEntity m_entity = new DynamicEntity();
            m_type = m_entity.GetType();
//            m_entityType = EntityName.DynamicE .Dyn.discounttype.ToString();
        }

        public override BusinessEntity GetBusinessEntity()
        {
            return new DynamicEntity();
        }

        public override string CreateEntity(XmlDocument instanceXML, CrmService webService, BusinessEntity m_entity, DbPopulator dbPopulator)
        {
            bool quiet = dbPopulator.QuietMode;
            ((DynamicEntity)m_entity).Name = instanceXML.SelectSingleNode("//name").InnerText;
            XmlNodeList propertyList = instanceXML.SelectNodes("//property");
			
            ((DynamicEntity)m_entity).Properties = new Property[propertyList.Count];
            for (int j = 0; j < propertyList.Count; j++)
            {
                XmlNode child = propertyList[j];
                switch (child.Attributes["type"].Value)
                {
                    case "string":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateStringProperty(child.Attributes["name"].Value, child.Attributes["value"].Value);
                        break;
                    case "owner":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateOwnerProperty(child.Attributes["name"].Value,CrmTypes.CreateOwner(EntityName.systemuser.ToString(), new Guid(child.Attributes["value"].Value)));
                        break;
                    case "picklist":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreatePicklistProperty(child.Attributes["name"].Value, CrmTypes.CreatePicklist(int.Parse(child.Attributes["value"].Value)));
                        break;
                    case "money":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateCrmMoneyProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmMoney(decimal.Parse(child.Attributes["value"].Value)));
                        break;
                    case "boolean":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateCrmBooleanProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmBoolean(bool.Parse(child.Attributes["value"].Value)));
                        break;
                    case "decimal":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateCrmDecimalProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmDecimal(decimal.Parse(child.Attributes["value"].Value)));
                        break;
                    case "datetime":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateCrmDateTimeProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmDateTime(child.Attributes["value"].Value));
                        break;
                    case "float":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateCrmFloatProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmFloat(float.Parse(child.Attributes["value"].Value)));
                        break;
                    case "lookup":
                        ((DynamicEntity)m_entity).Properties[j] = CrmTypes.CreateLookupProperty(child.Attributes["name"].Value, CrmTypes.CreateLookup(EntityName.account.ToString(), new Guid(child.Attributes["value"].Value)));
                        break;
                    default:
                        Console.WriteLine(child.Attributes["type"].Value + " is not implemented yet. Needs to be implemented to generate Property");
                        break;
                }
            }

            TargetCreateDynamic target = new TargetCreateDynamic();
            target.Entity = (DynamicEntity)m_entity;

            CreateRequest req = new CreateRequest();
            req.Target = target;

            try
            {
                CreateResponse resp = (CreateResponse)webService.Execute(req);
                Guid createdId = resp.id;
                if(!quiet)
                    Console.WriteLine("Created Dynamic Entity [" + ((DynamicEntity)m_entity).Name + "] with id = {0}", createdId.ToString());
                return createdId.ToString();
            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {
                string err = string.Format("{0}\r\n", ex.ToString());
                err = err + string.Format("Soap Exception Detail: {0}\r\n", ex.Detail.InnerXml);
                Console.WriteLine(err);
                return null;
            }
            catch (Exception ex)
            {
                string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
                    Thread.CurrentThread.GetHashCode());
                err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
                err = err + ex.ToString();
                Console.WriteLine(err);
                return null;
            }
        }

        private static string m_entityXmlString =
            @"<DynamicEntity>
                <name></name>
                <property type=""owner"" name=""ownerid"" value=""replace(owneridreplace)"" />
		    </DynamicEntity>";
    };

	public class CrmEmailTemplate : CrmEntityTemplate
	{
		public CrmEmailTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			email m_entity = new email();
			m_type = m_entity.GetType();
			m_entityType = EntityName.email.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new email();
		}

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
            string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{
				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "cancel")
						{
							SetStateEmailRequest setStateEmailReq = new SetStateEmailRequest();
							setStateEmailReq.EntityId = new Guid(entityId);
							setStateEmailReq.EmailState = EmailState.Canceled;
							setStateEmailReq.EmailStatus = -1;
							webService.Execute(setStateEmailReq);
							if(!quiet)
								Console.WriteLine("Email with id = {0} updated successfully to cancel state", entityId);
						}
						else if(n.InnerText.ToLower() == "complete")
						{
							SetStateEmailRequest setStateEmailReq = new SetStateEmailRequest();
							setStateEmailReq.EntityId = new Guid(entityId);
							setStateEmailReq.EmailState = EmailState.Completed;
							setStateEmailReq.EmailStatus = -1;
							webService.Execute(setStateEmailReq);
							if(!quiet)
								Console.WriteLine("Email with id = {0} updated successfully to complete state", entityId);
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}

		}

		

		private static string m_entityXmlString =
			@"<email>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<description>replace(randomdescription,5)</description>
				<from></from>
				<to></to>
    			<sender></sender>
    			<torecipients></torecipients>
    			<subcategory>replace(randomstring)</subcategory>
    			<prioritycode>1</prioritycode>
    			<actualdurationminutes>30</actualdurationminutes>
    			<category>replace(randomstring)</category>
    			<subject>replace(randomsubject)</subject>
    			<regardingobjectid></regardingobjectid>
    		</email>";
	};

	public class CrmEquipmentTemplate : CrmEntityTemplate
	{
		public CrmEquipmentTemplate()
		{
			m_entityXml.LoadXml(m_entityXmlString);
			equipment m_entity = new equipment();
			m_type = m_entity.GetType();
			m_entityType = EntityName.equipment.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new equipment();
		}

		private static string m_entityXmlString =
			@"<equipment>
				<name>replace(randomname)</name>
				<timezonecode>4</timezonecode>
			</equipment>";
	};

	public class CrmFaxTemplate : CrmEntityTemplate
	{
		public CrmFaxTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			fax m_entity = new fax();
			m_type = m_entity.GetType();
			m_entityType = EntityName.fax.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new fax();
		}

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{
				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "cancel")
						{
							SetStateFaxRequest setStateFaxReq = new SetStateFaxRequest();
							setStateFaxReq.EntityId = new Guid(entityId);
							setStateFaxReq.FaxState = FaxState.Canceled;
							setStateFaxReq.FaxStatus = -1;
							webService.Execute(setStateFaxReq);
							if(!quiet)
								Console.WriteLine("Fax with id = {0} updated successfully to cancel state", entityId);
						}
						else if(n.InnerText.ToLower() == "complete")
						{
							SetStateFaxRequest setStateFaxReq = new SetStateFaxRequest();
							setStateFaxReq.EntityId = new Guid(entityId);
							setStateFaxReq.FaxState = FaxState.Completed;
							setStateFaxReq.FaxStatus = -1;
							webService.Execute(setStateFaxReq);
							if(!quiet)
								Console.WriteLine("Fax with id = {0} updated successfully to conplete state", entityId);
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}
		}

		private static string m_entityXmlString =
			@"<fax>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<description>replace(randomdescription,5)</description>
    			<faxnumber>replace(randomphone)</faxnumber>
    			<subcategory>replace(randomstring)</subcategory>
    			<prioritycode>1</prioritycode>
    			<actualdurationminutes>30</actualdurationminutes>
    			<scheduledend>replace(randomtime)</scheduledend>
    			<category>replace(randomstring)</category>
    			<subject>replace(randomsubject)</subject>
    			<regardingobjectid.Value></regardingobjectid.Value>
				<regardingobjectid.type></regardingobjectid.type>
    		</fax>";
	};

	public class CrmInvoiceTemplate : CrmEntityTemplate
	{
		public CrmInvoiceTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			invoice m_entity = new invoice();
			m_type = m_entity.GetType();
			m_entityType = EntityName.invoice.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new invoice();
		}

		private static string m_entityXmlString =
			@"<invoice>
    			<name>replace(randomsalesorder)</name>
    			<customerid.Value></customerid.Value>
				<customerid.type></customerid.type>
    			<willcall>0</willcall>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<pricelevelid></pricelevelid>
    			<statuscode>1</statuscode>
    			<opportunityid></opportunityid>
    		</invoice>";
	};

	public class CrmInvoiceDetailTemplate : CrmEntityTemplate
	{
		public CrmInvoiceDetailTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			invoicedetail m_entity = new invoicedetail();
			m_type = m_entity.GetType();
			m_entityType = EntityName.invoicedetail.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new invoicedetail();
		}

		private static string m_entityXmlString =
			@"<invoicedetail>
    			<invoiceid></invoiceid>
    			<description>replace(randomdescription,3)</description>
    			<quantity>replace(randomnumber)</quantity>
    			<productid></productid>
    			<uomid></uomid>
    		</invoicedetail>";
	};

	public class CrmKbArticleTemplate : CrmEntityTemplate
	{
		public CrmKbArticleTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			kbarticle m_entity = new kbarticle();
			m_type = m_entity.GetType();
			m_entityType = EntityName.kbarticle.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new kbarticle();
		}

		private static string m_entityXmlString =
			@"<kbarticle>
    			<title>replace(randomsubject)</title>
				<kbarticletemplateid></kbarticletemplateid>
				<articlexml></articlexml>
    			<description>replace(randomdescription)</description>
    			<subjectid></subjectid>
    		</kbarticle>";
	};


	public class CrmLeadTemplate : CrmEntityTemplate
	{
		public CrmLeadTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			lead m_entity = new lead();
			m_type = m_entity.GetType();
			m_entityType = EntityName.lead.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new lead();
		}

		private static string m_entityXmlString =
            @"<lead>
				<ownerid>replace(owneridreplace)</ownerid>
				<customerid.Value></customerid.Value>
				<customerid.type></customerid.type>
                <firstname>replace(randomfirstname)</firstname>
                <lastname>replace(randomlastname)</lastname>
                <companyname>replace(randomname)</companyname>
                <address1_line1>replace(randomaddressline1)</address1_line1>
                <address1_city>replace(randomcity)</address1_city>
                <address1_stateorprovince>replace(randomstate)</address1_stateorprovince>
                <address1_country>replace(randomcountry)</address1_country>
                <address1_postalcode>replace(randomnumber,10000,99999)</address1_postalcode>
                <address1_telephone1>replace(randomphone)</address1_telephone1>
                <address1_name>First Lead Address</address1_name>
                <emailaddress1>replace(randomemail)</emailaddress1>
                <subject>replace(randomsubject)</subject>
                <jobtitle>replace(randomjobtitle)</jobtitle>
                <mobilephone>replace(randomphone)</mobilephone>
                <telephone1>replace(randomphone)</telephone1>
                <telephone2>replace(randomphone)</telephone2>
                <fax>replace(randomphone)</fax>
                <description>replace(randomdescription)</description>
             </lead>";
	};

	public class CrmLetterTemplate : CrmEntityTemplate
	{
		public CrmLetterTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			letter m_entity = new letter();            
			m_type = m_entity.GetType();
			m_entityType = EntityName.letter.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new letter();
		}

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{
				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "cancel")
						{
							SetStateLetterRequest setStateLetterReq = new SetStateLetterRequest();
							setStateLetterReq.EntityId = new Guid(entityId);
							setStateLetterReq.LetterState = LetterState.Canceled;
							setStateLetterReq.LetterStatus = -1;
							webService.Execute(setStateLetterReq);
							if(!quiet)
								Console.WriteLine("Letter with id = {0} updated successfully to cancel state", entityId);
						}
						else if(n.InnerText.ToLower() == "complete")
						{
							SetStateLetterRequest setStateLetterReq = new SetStateLetterRequest();
							setStateLetterReq.EntityId = new Guid(entityId);
							setStateLetterReq.LetterState = LetterState.Completed;
							setStateLetterReq.LetterStatus = -1;
							webService.Execute(setStateLetterReq);
							if(!quiet)	
								Console.WriteLine("Letter with id = {0} updated successfully to complete state", entityId);
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}

		}

		private static string m_entityXmlString =
			@"<letter>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<description>replace(randomdescription,5)</description>
				<from></from>
				<to></to>
    			<address>replace(randomaddress)</address>
    			<subcategory>replace(randomstring)</subcategory>
    			<prioritycode>1</prioritycode>
    			<actualdurationminutes>30</actualdurationminutes>
    			<scheduledend>replace(randomtime)</scheduledend>
    			<category>replace(randomstring)</category>
    			<subject>replace(randomsubject)</subject>
    			<regardingobjectid.Value></regardingobjectid.Value>
				<regardingobjectid.type></regardingobjectid.type>
    		</letter>";
	};

	public class CrmListTemplate : CrmEntityTemplate
	{
		public CrmListTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			list m_entity = new list();
			m_type = m_entity.GetType();
			m_entityType = EntityName.list.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new list();
		}

		private static string m_entityXmlString =
			@"<list>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<description>replace(randomdescription, 5)</description>
				<listname>replace(randomname)</listname>
				<createdfromcode>1</createdfromcode>
				<createdon>replace(randomdate,-60.0)</createdon>
				<modifiedon>replace(randomdate,-30.0)</modifiedon>
    		</list>";
	};

	public class CrmListMemberTemplate : CrmEntityTemplate
	{
		public CrmListMemberTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			listmember m_entity = new listmember();
			m_type = m_entity.GetType();
			m_entityType = EntityName.listmember.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new listmember();
		}

		public override string CreateEntity (XmlDocument instanceXML, CrmService webService, BusinessEntity m_entity, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
			{
				XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
				if (n.InnerText != "") 
				{
					try
					{
						AddAttribute ( n.Name, ref m_entity, n.InnerText);
					}
					catch (Exception e)
					{
						string err = string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), e.Message);
						err = err + "Skipping entering the value of the parameter\r\n";
						err = err + e.ToString();
						FileWriter.Instance.WriteToFile(err);
					}
				}
			}

			AddMemberListRequest addMemberListRequest = new AddMemberListRequest();
			addMemberListRequest.EntityId = ((listmember)m_entity).entityid.Value;
			addMemberListRequest.ListId = ((listmember)m_entity).listid.Value;
			
			try
			{
	
				Microsoft.Crm.Sdk.Proxy.Response response = webService.Execute(addMemberListRequest);
				AddMemberListResponse addMemberListResponse = response as AddMemberListResponse;
				
				string entityId = addMemberListResponse.Id.ToString();
				if(!quiet)
					Console.WriteLine("ListMember with id = {0} created", entityId);
				return entityId;
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail:" + ex.Detail.InnerXml);
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
		}

		private static string m_entityXmlString =
			@"<list>
				<listid></listid>
				<entityid></entityid>
				<entitytype></entitytype>
    			<owninguser>replace(owneridreplace)</owninguser>
    		</list>";
	};

	public class CrmOpportunityTemplate : CrmEntityTemplate
	{
		public CrmOpportunityTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			opportunity m_entity = new opportunity();
			m_type = m_entity.GetType();
			m_entityType = EntityName.opportunity.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new opportunity();
		}

		private static string m_entityXmlString =
			@"<opportunity>
    			<name>replace(randomopportunity)</name>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<customerid.Value></customerid.Value>
				<customerid.type></customerid.type>
    			<opportunityratingcode>2</opportunityratingcode>
    			<statuscode>1</statuscode>
    			<estimatedvalue>replace(randomnumber)</estimatedvalue>
				<actualvalue>replace(randomnumber)</actualvalue>
    			<description>replace(randomdescription)</description>
    			<pricelevelid></pricelevelid>
				<estimatedclosedate>replace(randomdate)</estimatedclosedate>
    		</opportunity>";

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{
				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "win")
						{
							opportunityclose opportunityclose = new opportunityclose();
							opportunityclose.opportunityid = new Lookup();
							opportunityclose.opportunityid.Value = new Guid(entityId);
							opportunityclose.ownerid = new Owner();
							opportunityclose.ownerid.Value = new Guid(ownerid);
							opportunityclose.ownerid.type = EntityName.systemuser.ToString();
							WinOpportunityRequest winRequest= new WinOpportunityRequest();
							winRequest.OpportunityClose = opportunityclose;
							winRequest.Status = -1;
							webService.Execute(winRequest);
							return;
						}
						if(n.InnerText.ToLower() == "lose")
						{
							opportunityclose opportunityclose = new opportunityclose();
							opportunityclose.opportunityid = new Lookup();
							opportunityclose.opportunityid.Value = new Guid(entityId);
							opportunityclose.ownerid = new Owner();
							opportunityclose.ownerid.Value = new Guid(ownerid);
							opportunityclose.ownerid.type = EntityName.systemuser.ToString();
							LoseOpportunityRequest loseRequest= new LoseOpportunityRequest();
							loseRequest.OpportunityClose = opportunityclose;
							loseRequest.Status = -1;
							webService.Execute(loseRequest);
							return;
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}
		}
	};

	public class CrmOpportunityProductTemplate : CrmEntityTemplate
	{
		public CrmOpportunityProductTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			opportunityproduct m_entity = new opportunityproduct();
			m_type = m_entity.GetType();
			m_entityType = EntityName.opportunityproduct.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new opportunityproduct();
		}

		private static string m_entityXmlString =
			@"<opportunityproduct>
    			<opportunityid></opportunityid>
    			<description>replace(randomdescription)</description>
    			<quantity></quantity>
    			<productid></productid>
    			<uomid></uomid>
    		</opportunityproduct>";
	};

	public class CrmPhoneCallTemplate : CrmEntityTemplate
	{
		public CrmPhoneCallTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			phonecall m_entity = new phonecall();
			m_type = m_entity.GetType();
			m_entityType = EntityName.phonecall.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new phonecall();
		}

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{
				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "cancel")
						{
							SetStatePhoneCallRequest setStatePhoneCallReq = new SetStatePhoneCallRequest();
							setStatePhoneCallReq.EntityId = new Guid(entityId);
							setStatePhoneCallReq.PhoneCallState = PhoneCallState.Canceled;
							setStatePhoneCallReq.PhoneCallStatus = -1;
							webService.Execute(setStatePhoneCallReq);
							if(!quiet)
								Console.WriteLine("PhoneCall with id = {0} updated successfully to cancel state", entityId);
						}
						else if(n.InnerText.ToLower() == "complete")
						{
							SetStatePhoneCallRequest setStatePhoneCallReq = new SetStatePhoneCallRequest();
							setStatePhoneCallReq.EntityId = new Guid(entityId);
							setStatePhoneCallReq.PhoneCallState = PhoneCallState.Completed;
							setStatePhoneCallReq.PhoneCallStatus = -1;
							webService.Execute(setStatePhoneCallReq);
							if(!quiet)
								Console.WriteLine("PhoneCall with id = {0} updated successfully to complete state", entityId);
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}

		}
		
		private static string m_entityXmlString =
			@"<phonecall>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<description>replace(randomdescription)</description>
				<from></from>
				<to></to>
    			<phonenumber>replace(randomphone)</phonenumber>
    			<subcategory>replace(randomstring)</subcategory>
    			<prioritycode>1</prioritycode>
    			<actualdurationminutes>30</actualdurationminutes>
    			<scheduledend>replace(randomtime)</scheduledend>
    			<category>replace(randomstring)</category>
    			<subject>replace(randomsubject)</subject>
    			<regardingobjectid.Value></regardingobjectid.Value>
				<regardingobjectid.type></regardingobjectid.type>
    		</phonecall>";
	};

	public class CrmPriceLevelTemplate : CrmEntityTemplate
	{
		public CrmPriceLevelTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			pricelevel m_entity = new pricelevel();
			m_type = m_entity.GetType();
			m_entityType = EntityName.pricelevel.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new pricelevel();
		}

		private static string m_entityXmlString =
			@"<pricelevel>
    			<name>pricelevel for customers of type + replace(getnextnumbertick)</name>
    			<begindate>2000-01-01T00:00:00</begindate>
    			<enddate>2009-01-01T00:00:00</enddate>
    		</pricelevel>";
	};

	public class CrmProductTemplate : CrmEntityTemplate
	{
		public CrmProductTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			product m_entity = new product();
			m_type = m_entity.GetType();
			m_entityType = EntityName.product.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new product();
		}

		private static string m_entityXmlString =
			@"<product>
    			<name>replace(randomproduct)</name>
	 			<productnumber>replace(getnexttick)</productnumber>
    			<defaultuomscheduleid></defaultuomscheduleid>
    			<defaultuomid></defaultuomid>
    			<quantitydecimal>0</quantitydecimal>
				<standardcost>replace(randomnumber,1,50)</standardcost>
				<currentcost>replace(randomnumber,1,50)</currentcost>
    		</product>";
	};

	public class CrmProductPriceLevelTemplate : CrmEntityTemplate
	{
		public CrmProductPriceLevelTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			productpricelevel m_entity = new productpricelevel();
			m_type = m_entity.GetType();
			m_entityType = EntityName.productpricelevel.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new productpricelevel();
		}

		private static string m_entityXmlString =
			@"<productpricelevel>
    			<productid></productid>
    			<uomscheduleid></uomscheduleid>
    			<pricelevelid></pricelevelid>
    			<uomid></uomid>
    			<quantitysellingcode>1</quantitysellingcode>
    			<pricingmethodcode>1</pricingmethodcode>
    			<amount>replace(randomnumber,10,100)</amount>
    		</productpricelevel>";
	};

	public class CrmQuoteTemplate : CrmEntityTemplate
	{
		public CrmQuoteTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			quote m_entity = new quote();
			m_type = m_entity.GetType();
			m_entityType = EntityName.quote.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new quote();
		}

		private static string m_entityXmlString =
			@"<quote>
    			<name>replace(randomquote)</name>
    			<customerid.Value></customerid.Value>
				<customerid.type></customerid.type>
    			<pricelevelid></pricelevelid>
    			<discountpercentage>replace(randomnumber,1,15)</discountpercentage>
    			<effectivefrom>2000-01-01</effectivefrom>
    			<effectiveto>2099-12-31</effectiveto>
    			<requestdeliveryby>2099-12-31</requestdeliveryby>
    			<expireson>2099-12-31</expireson>
    			<description>replace(randomdescription)</description>
    			<billto_name>replace(randomname)</billto_name>
    			<billto_stateorprovince>replace(randomstate)</billto_stateorprovince>
    			<billto_line1>replace(randomaddressline1)</billto_line1>
    			<billto_postalcode>replace(randomnumber,10000,99999)</billto_postalcode>
    			<billto_country>replace(randomcountry)</billto_country>
    			<billto_telephone>replace(randomphone)</billto_telephone>
    			<billto_city>replace(randomcity)</billto_city>
    			<billto_fax>replace(randomphone)</billto_fax>
    			<willcall>0</willcall>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<statuscode>1</statuscode>
				<statecode></statecode>
				<opportunityid></opportunityid>
    		</quote>";

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;
			try
			{

				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "active")
						{
							SetStateQuoteRequest stateQuoteRequest = new SetStateQuoteRequest();
							stateQuoteRequest.QuoteState = QuoteState.Active;
							stateQuoteRequest.QuoteStatus = -1;
							stateQuoteRequest.EntityId = new Guid(entityId);
							webService.Execute (stateQuoteRequest);
							return;

						}
						if(n.InnerText.ToLower() == "close")
						{
							SetStateQuoteRequest stateQuoteRequest = new SetStateQuoteRequest();
							stateQuoteRequest.QuoteState = QuoteState.Active;
							stateQuoteRequest.QuoteStatus = -1;
							stateQuoteRequest.EntityId = new Guid(entityId);
							webService.Execute (stateQuoteRequest);

							quoteclose quoteclose = new quoteclose();
							quoteclose.quoteid = new Lookup();
							quoteclose.quoteid.Value = new Guid(entityId);
							quoteclose.ownerid = new Owner();
							quoteclose.ownerid.Value = new Guid(ownerid);
							quoteclose.ownerid.type = EntityName.systemuser.ToString();

							CloseQuoteRequest closeReq = new CloseQuoteRequest();
							closeReq.QuoteClose = quoteclose;
							closeReq.Status = -1;
							
							webService.Execute(closeReq);
							return;
						}
						if(n.InnerText.ToLower() == "win")
						{
							SetStateQuoteRequest stateQuoteRequest = new SetStateQuoteRequest();
							stateQuoteRequest.QuoteState = QuoteState.Active;
							stateQuoteRequest.QuoteStatus = -1;
							stateQuoteRequest.EntityId = new Guid(entityId);
							webService.Execute (stateQuoteRequest);

							quoteclose quoteclose = new quoteclose();
							quoteclose.quoteid = new Lookup();
							quoteclose.quoteid.Value = new Guid(entityId);
							quoteclose.ownerid = new Owner();
							quoteclose.ownerid.Value = new Guid(ownerid);
							quoteclose.ownerid.type = EntityName.systemuser.ToString();

							WinQuoteRequest winReq = new WinQuoteRequest();
							winReq.QuoteClose = quoteclose;
							winReq.Status = -1;
							webService.Execute(winReq);
							return;
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}
		}
	};

	public class CrmQuoteDetailTemplate : CrmEntityTemplate
	{
		public CrmQuoteDetailTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			quotedetail m_entity = new quotedetail();
			m_type = m_entity.GetType();
			m_entityType = EntityName.quotedetail.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new quotedetail();
		}

		private static string m_entityXmlString =
			@"<quotedetail>
    			<quoteid></quoteid>
				<quotestatecode></quotestatecode>
    			<quantity>replace(randomnumber)</quantity>
    			<description>replace(randomdescription,5)</description>
    			<productid></productid>
    			<uomid></uomid>
    		</quotedetail>";
	};

	public class CrmResourceSpecTemplate : CrmEntityTemplate
	{
		public CrmResourceSpecTemplate()
		{
			m_entityXml.LoadXml(m_entityXmlString);
			resourcespec m_entity = new resourcespec();
			m_type = m_entity.GetType();
			m_entityType = EntityName.resourcespec.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new resourcespec();
		}

		private const string RandomObjective = "<Expression><Body>udf \"Random\"(factory,resource,appointment,request,leftoffset,rightoffset)</Body><Parameters><Parameter name=\"factory\" /><Parameter name=\"resource\" /><Parameter name=\"appointment\" /><Parameter name=\"request\" /><Parameter name=\"leftoffset\" /><Parameter name=\"rightoffset\" /></Parameters><Properties EvaluationInterval=\"P0D\" evaluationcost=\"0\" /></Expression>";

		private static string m_entityXmlString =
			@"<resourcespec>
				<name>replace(randomname)</name>
				<objecttypecode>constraintbasedgroup</objecttypecode>
				<objectiveexpression>" + RandomObjective + @"</objectiveexpression>
				<requiredcount>1</requiredcount>
				<effortrequired>1</effortrequired>
				<samesite>1</samesite>
			</resourcespec>";
	};

	public class CrmSystemUserRoleTemplate : CrmEntityTemplate
    {
        public CrmSystemUserRoleTemplate()
        {
            m_entityXml.LoadXml(m_entityXmlString);
            role m_entity = new role();
            m_type = m_entity.GetType();
            m_entityType = EntityName.role.ToString();

            m_roleTemplateId = new Hashtable();
            m_roleTemplateId.Add("CEO-Business Manager",new Guid("85937B6B-91A1-46ED-9778-929FC9F61812"));
            m_roleTemplateId.Add("Vice President of Sales", new Guid("29123793-6AE5-4955-9F1A-F10CEB9705F1"));
            m_roleTemplateId.Add("Sales Manager", new Guid("C0ED2F4F-6F92-4691-92BA-78F2931E8FBA"));
            m_roleTemplateId.Add("Salesperson", new Guid("A4BE89FF-7C35-4D69-9900-999C3F603E6F"));
            m_roleTemplateId.Add("Customer Service Representative", new Guid("ECFD0B44-5720-45E3-AE68-417DDB0FB654"));
            m_roleTemplateId.Add("CSR Manager", new Guid("1808B939-DD07-4CA7-AA99-DDD2734378F1"));
            m_roleTemplateId.Add("Marketing Professional", new Guid("09A25608-D28B-4D47-B57C-79271FE6A525"));
            m_roleTemplateId.Add("System Administrator", new Guid("627090FF-40A3-4053-8790-584EDC5BE201"));
            m_roleTemplateId.Add("Schedule Manager", new Guid("DEBEC338-BCA7-4882-AE04-84E6DDDA2984"));
            m_roleTemplateId.Add("Vice President of Marketing", new Guid("6CABA073-59A8-4D6B-8E7B-4CCB50C5166B"));
            m_roleTemplateId.Add("Marketing Manager", new Guid("D9D602DB-2761-4170-877F-983494567C08"));
            m_roleTemplateId.Add("Scheduler", new Guid("DCD60B89-421C-44ae-BFF0-DD6323DF885C"));
            m_roleTemplateId.Add("System Customizer", new Guid("119F245C-3CC8-4b62-B31C-D1A046CED15D"));
        }

        public override BusinessEntity GetBusinessEntity()
        {
            return new role();
        }

        public override string CreateEntity(XmlDocument instanceXML, CrmService webService, BusinessEntity m_entity, DbPopulator dbPopulator)
        {
            bool quiet = dbPopulator.QuietMode;
            role roleRet = null;

            // Retrieve the Role with the given name for the particular Business Unit first
            Guid businessunitid = new Guid(instanceXML.DocumentElement.SelectSingleNode("businessunitid").InnerText);
            QueryExpression query1 = new QueryExpression();
            query1.EntityName = "role";
            ColumnSet columnSet = new ColumnSet();

            columnSet.Attributes = new string[] { "roleid" };
            query1.ColumnSet = columnSet;
            ConditionExpression[] ceArray = new ConditionExpression[2];
            if (m_roleTemplateId.ContainsKey(instanceXML.DocumentElement.SelectSingleNode("name").InnerText))
            {
                ceArray[0] = new ConditionExpression();
                ceArray[0].AttributeName = "roletemplateid";
                ceArray[0].Operator = ConditionOperator.Equal;
                ceArray[0].Values = new object[] { (Guid)m_roleTemplateId[instanceXML.DocumentElement.SelectSingleNode("name").InnerText] };
            }
            else
            {
                FileWriter.Instance.WriteToFile("Name of the role is wrongly spelt, hence can't add the role to user");
                return null;
            }
            ceArray[1] = new ConditionExpression();
            ceArray[1].AttributeName = "businessunitid";
            ceArray[1].Operator = ConditionOperator.Equal;
            ceArray[1].Values = new object[] { businessunitid };

            query1.Criteria = new FilterExpression();
            query1.Criteria.Conditions = ceArray;

            try
            {
                BusinessEntityCollection results = webService.RetrieveMultiple(query1);
                if (results != null && results.BusinessEntities.Length > 0)
                {
                    BusinessEntity[] rolesReturned = results.BusinessEntities;
                    roleRet = (role)rolesReturned[0];
                }
                else
                {
                    Console.WriteLine("No roles with the name of '{0}' found, not adding any roles", instanceXML.DocumentElement.SelectSingleNode("name").InnerText);
                }
            }
            catch (System.Web.Services.Protocols.SoapException ex)
            {
                FileWriter.Instance.WriteToFile(string.Format("{0}\r\nSoap Exception Detail: {1}", ex.ToString(), ex.Detail.InnerXml));
            }

            if (roleRet != null)
            {
                AssignUserRolesRoleRequest assignRole = new AssignUserRolesRoleRequest();
                assignRole.RoleIds = new Guid[1];
                assignRole.RoleIds[0] = roleRet.roleid.Value;
                assignRole.UserId = new Guid(instanceXML.DocumentElement.SelectSingleNode("userid").InnerText);

                try
                {
                    webService.Execute(assignRole);
                    if (!quiet)
                    {
                        Console.WriteLine("User with id = {0} assigned roleid = {1}", instanceXML.DocumentElement.SelectSingleNode("userid").InnerText, roleRet.roleid.Value.ToString());
                    }
                    return "";
                }
                catch (System.Web.Services.Protocols.SoapException ex)
                {
                    string err = string.Format("{0}\r\n", ex.ToString());
                    err = err + string.Format("Soap Exception Detail: {0}\r\n", ex.Detail.InnerXml);
                    err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
                    FileWriter.Instance.WriteToFile(err);
                    return null;
                }
                catch (Exception ex)
                {
                    string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
                       Thread.CurrentThread.GetHashCode());
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
                    err = err + ex.ToString();
                    FileWriter.Instance.WriteToFile(err);
                    return null;
                }
            }
            else
            {
                Console.WriteLine("No Role with the name was found for the specified BU, unable to add role for user for BU");
                return "";
            }
        }

        Hashtable m_roleTemplateId;

        
        private static string m_entityXmlString =
            @"<userrole>
    			<userid></userid>
                <businessunitid></businessunitid>
                <name></name>				
    		</userrole>";
    };

	public class CrmSalesLiteratureTemplate : CrmEntityTemplate
	{
		public CrmSalesLiteratureTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			salesliterature m_entity = new salesliterature();
			m_type = m_entity.GetType();
			m_entityType = EntityName.salesliterature.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new salesliterature();
		}

		private static string m_entityXmlString =
			@"<salesliterature>
    			<name>replace(randomname)</name>
    			<description>replace(randomdescription)</description>
    			<subjectid></subjectid>
				<literaturetypecode>1</literaturetypecode>
    		</salesliterature>";
	};

	public class CrmSalesOrderDetailTemplate : CrmEntityTemplate
	{
		public CrmSalesOrderDetailTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			salesorderdetail m_entity = new salesorderdetail();
			m_type = m_entity.GetType();
			m_entityType = EntityName.salesorderdetail.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new salesorderdetail();
		}

		private static string m_entityXmlString =
			@"<salesorderdetail>
    			<salesorderid></salesorderid>
    			<description>replace(randomdescription,3)</description>
    			<quantity>replace(randomnumber)</quantity>
    			<productid></productid>
    			<uomid></uomid>
    		</salesorderdetail>";
	};

	public class CrmSalesOrderTemplate : CrmEntityTemplate
	{
		public CrmSalesOrderTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			salesorder m_entity = new salesorder();
			m_type = m_entity.GetType();
			m_entityType = EntityName.salesorder.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new salesorder();
		}

		private static string m_entityXmlString =
			@"<salesorder>
    			<name>replace(randomsalesorder)</name>
    			<customerid.Value></customerid.Value>
				<customerid.type></customerid.type>
    			<willcall>0</willcall>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<pricelevelid></pricelevelid>
    			<statuscode>1</statuscode>
    			<opportunityid></opportunityid>
    		</salesorder>";

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{

				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "fulfill")
						{
							orderclose orderclose = new orderclose();
							orderclose.salesorderid = new Lookup();
							orderclose.salesorderid.Value = new Guid(entityId);
							orderclose.ownerid = new Owner();
							orderclose.ownerid.Value = new Guid(ownerid);
							orderclose.ownerid.type = EntityName.systemuser.ToString();
							FulfillSalesOrderRequest fulfilledRequest= new FulfillSalesOrderRequest();
							fulfilledRequest.OrderClose = orderclose;
							fulfilledRequest.Status = -1;
							webService.Execute(fulfilledRequest);
							return;
						}
						if(n.InnerText.ToLower() == "cancel")
						{
							orderclose orderclose = new orderclose();
							orderclose.salesorderid = new Lookup();
							orderclose.salesorderid.Value = new Guid(entityId);
							orderclose.ownerid = new Owner();
							orderclose.ownerid.Value = new Guid(ownerid);
							orderclose.ownerid.type = EntityName.systemuser.ToString();
							CancelSalesOrderRequest cancelRequest= new CancelSalesOrderRequest();
							cancelRequest.OrderClose = orderclose;
							cancelRequest.Status = -1;
							webService.Execute(cancelRequest);
							return;
						}
						if(n.InnerText.ToLower() == "submit")
						{
							SetStateSalesOrderRequest stateSalesOrderRequest = new SetStateSalesOrderRequest();
							stateSalesOrderRequest.SalesOrderState = SalesOrderState.Submitted;
							stateSalesOrderRequest.EntityId = new Guid(entityId);
							stateSalesOrderRequest.SalesOrderStatus = -1;
							webService.Execute(stateSalesOrderRequest);
							return;
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}
		}
	};

	public class CrmServiceTemplate : CrmEntityTemplate
	{
		public CrmServiceTemplate()
		{
			m_entityXml.LoadXml(m_entityXmlString);
			service m_entity = new service();
			m_type = m_entity.GetType();
			m_entityType = EntityName.service.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new service();
		}

		private static string m_entityXmlString =
			@"<service>
				<granularity>FREQ=MINUTELY;INTERVAL=15;</granularity>
				<anchoroffset>480</anchoroffset>
				<name>replace(randomname)</name>
				<initialstatuscode>1</initialstatuscode>
				<strategyid>{07F7DC72-1671-452D-812C-7172D3CA881F}</strategyid>
				<duration>60</duration>
			</service>";
	};

	public class CrmServiceAppointmentTemplate : CrmEntityTemplate
	{
		public CrmServiceAppointmentTemplate()
		{

			m_entityXml.LoadXml(m_entityXmlString);
			serviceappointment m_entity = new serviceappointment();
			m_type = m_entity.GetType();
			m_entityType = EntityName.serviceappointment.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new serviceappointment();
		}

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			try
			{
				SetStateServiceAppointmentRequest setStateReq = new SetStateServiceAppointmentRequest();
				setStateReq.EntityId = new Guid(entityId);
				setStateReq.ServiceAppointmentState = ServiceAppointmentState.Scheduled;
				setStateReq.ServiceAppointmentStatus = 4;
				webService.Execute(setStateReq);
				if (!quiet)
					Console.WriteLine("ServiceAppointment with id = {0} updated successfully to scheduled state", entityId);
			}
			catch (System.Web.Services.Protocols.SoapException ex)
			{
				string err = string.Format("{0}\r\n", ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n", ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}
		}

		private static string m_entityXmlString =
            @"<serviceappointment>
				<subject>replace(randomsubject)</subject>
				<statuscode>1</statuscode>
				<scheduledstart>replace(randomstarttime)</scheduledstart>				
				<scheduleddurationminutes>60</scheduleddurationminutes>
				<isalldayevent>0</isalldayevent>
				<ownerid>replace(owneridreplace)</ownerid>
				<prioritycode>1</prioritycode>
                <scheduledend>repfiltered(scheduledstart,randomendtime,60)</scheduledend>
			</serviceappointment>";
	};

	public class CrmSubjectTemplate : CrmEntityTemplate
	{
		public CrmSubjectTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			subject m_entity = new subject();
			m_type = m_entity.GetType();
			m_entityType = EntityName.subject.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new subject();
		}

		private static string m_entityXmlString =
			@"<subject>
    			<featuremask>1</featuremask>
    			<title>replace(randomsubject)</title>
    			<description>replace(randomdescription,4)</description>
    		</subject>";
	};

	public class CrmTaskTemplate : CrmEntityTemplate
	{
		public CrmTaskTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			task m_entity = new task();
			m_type = m_entity.GetType();
			m_entityType = EntityName.task.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new task();
		}

		public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			string ownerid = instanceXML.DocumentElement.SelectSingleNode("ownerid").InnerText;

			try
			{

				for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
				{
					XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
					if(n.Name == "statecode")
					{
						if(n.InnerText.ToLower() == "cancel")
						{
							SetStateTaskRequest setStateTaskReq = new SetStateTaskRequest();
							setStateTaskReq.EntityId = new Guid(entityId);
							setStateTaskReq.TaskState = TaskState.Canceled;
							setStateTaskReq.TaskStatus = 6;
							webService.Execute(setStateTaskReq);
							if(!quiet)
								Console.WriteLine("Task with id = {0} updated successfully to cancel state", entityId);
						}
						else if (n.InnerText.ToLower() == "complete")
						{
							SetStateTaskRequest setStateTaskReq = new SetStateTaskRequest();
							setStateTaskReq.EntityId = new Guid(entityId);
							setStateTaskReq.TaskState = TaskState.Completed;
							setStateTaskReq.TaskStatus = 5;
							webService.Execute(setStateTaskReq);
							if(!quiet)
								Console.WriteLine("Task with id = {0} updated successfully to complete state", entityId);
						}
					}
				}
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail: {0}\r\n",ex.Detail.InnerXml);
				err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
				FileWriter.Instance.WriteToFile(err);
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
			}

		}

		private static string m_entityXmlString =
			@"<task>
    			<ownerid>replace(owneridreplace)</ownerid>
    			<description>replace(randomdescription,3)</description>
    			<subcategory>replace(randomstring)</subcategory>
    			<prioritycode>1</prioritycode>
    			<actualdurationminutes>30</actualdurationminutes>
    			<scheduledend>replace(randomtime)</scheduledend>
    			<category>replace(randomstring)</category>
    			<subject>replace(randomsubject)</subject>
    			<regardingobjectid.Value></regardingobjectid.Value>
				<regardingobjectid.type></regardingobjectid.type>
    		</task>";
	};

	public class CrmUoMTemplate : CrmEntityTemplate
	{
		public CrmUoMTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			uom m_entity = new uom();
			m_type = m_entity.GetType();
			m_entityType = EntityName.uom.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new uom();
		}

		private static string m_entityXmlString =
			@"<uom>
    			<name>Pack of + replace(getnextnumbertick)</name>
    			<uomscheduleid></uomscheduleid>
    			<quantity>replace(randomnumber,1,10000)</quantity>
    			<baseuom></baseuom>
    		</uom>";
	};

	public class CrmUoMScheduleTemplate : CrmEntityTemplate
	{
		public CrmUoMScheduleTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			BusinessEntity m_entity =  new uomschedule();
			m_type = m_entity.GetType();
			m_entityType = EntityName.uomschedule.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			BusinessEntity m_entity =  new uomschedule();
			return m_entity;
		}

		public override string CreateEntity (XmlDocument instanceXML, CrmService webService, BusinessEntity m_entity, DbPopulator dbPopulator)
		{
            bool quiet = dbPopulator.QuietMode;
			for (int i = 0; i < instanceXML.DocumentElement.ChildNodes.Count; i++)
			{
				XmlNode n =  instanceXML.DocumentElement.ChildNodes[i];
				if (n.InnerText != "") 
				{
					try
					{
						AddAttribute ( n.Name, ref m_entity, n.InnerText);
					}
					catch (Exception e)
					{
						string err = string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), e.Message);
						err = err + "Skipping entering the value of the parameter\r\n";
						err = err + e.ToString();
						FileWriter.Instance.WriteToFile(err);
					}
				}
			}

			try
			{
				((uomschedule)m_entity).baseuomname = "BaseUnit";
				Guid id = webService.Create(m_entity);

				string entityId = id.ToString();
				if(!quiet)
					Console.WriteLine("UoMSchedule with id = {0} created", entityId);
				return entityId;
			}
			catch (System.Web.Services.Protocols.SoapException ex) 
			{
				string err = string.Format("{0}\r\n",ex.ToString());
				err = err + string.Format("Soap Exception Detail:" + ex.Detail.InnerXml);
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
			catch (Exception ex)
			{
				string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
					Thread.CurrentThread.GetHashCode());
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
				err = err + string.Format("[{0}]WARNING:  {1}", Thread.CurrentThread.GetHashCode(), ex.Message);
				err = err + ex.ToString();
				FileWriter.Instance.WriteToFile(err);
				return null;
			}
		}

		private static string m_entityXmlString =
			@"<uomschedule>
    			<name>Unit measurements for + replace(randomname)</name>
    		</uomschedule>";
	};

	public class CrmSystemUserTemplate : CrmEntityTemplate
	{
		public CrmSystemUserTemplate ()
		{
			m_entityXml.LoadXml (m_entityXmlString);
			systemuser m_entity = new systemuser();
			m_type = m_entity.GetType();
			m_entityType = EntityName.systemuser.ToString();
		}

		public override BusinessEntity GetBusinessEntity()
		{
			return new systemuser();
		}
        
        public override void CallPostCreate(string entityId, XmlDocument instanceXML, CrmService webService, DbPopulator dbPopulator)
        {
            bool quiet = dbPopulator.QuietMode;
            if (instanceXML.DocumentElement.SelectSingleNode("passportuser") != null)
            {
                bool passportuser = bool.Parse(instanceXML.DocumentElement.SelectSingleNode("passportuser").InnerText);
                if (passportuser)
                {
                    if (instanceXML.DocumentElement.SelectSingleNode("PUID") != null)
                    {
                        //Temporary
                        Console.WriteLine("Calling AddPrincipalToConfigDb...");
                        Console.WriteLine("OrgId: " + dbPopulator.OrganizationId.ToString());
                        Console.WriteLine("systemuserid: " + entityId);
                        Console.WriteLine("authinfo: " + "P:" + instanceXML.DocumentElement.SelectSingleNode("PUID").InnerText);

                        if (dbPopulator.OrganizationId == Guid.Empty)
                        {
                            FileWriter.Instance.WriteToFile("Organization Id is empty when calling AddPrincipalToConfigDb");
                        }

                        Microsoft.Crm.Authentication.CrmPrincipal.AddPrincipalToConfigDB(dbPopulator.OrganizationId, new Guid(entityId), "P:" + instanceXML.DocumentElement.SelectSingleNode("PUID").InnerText);
                    }
                    else
                    {
                        // Assuming that if the PUID is missing, it is a domain user being added to Live environment and domainname must exist.
                        byte[] principalSid = Microsoft.Crm.BusinessEntities.SecurityUtils.GetSidFromAccount(instanceXML.DocumentElement.SelectSingleNode("domainname").InnerText);
                        Guid activeDirectoryGuid = Microsoft.Crm.BusinessEntities.SecurityUtils.GetGuidFromSid(principalSid);
                        byte[] sid = Microsoft.Crm.BusinessEntities.SecurityUtils.GetSidFromAD(activeDirectoryGuid);
                        SecurityIdentifier identifier = new SecurityIdentifier(sid, 0);
                        string authInfo = Microsoft.Crm.Authentication.CrmWindowsIdentity.GetUserToken(identifier);
                        Microsoft.Crm.Authentication.CrmPrincipal.AddPrincipalToConfigDB(dbPopulator.OrganizationId, new Guid(entityId), authInfo);
                    }
                }
            }

            if (instanceXML.DocumentElement.SelectSingleNode("uilanguageid") != null)
            {
                int languageid = int.Parse(instanceXML.DocumentElement.SelectSingleNode("uilanguageid").InnerText);
                usersettings userSettings = new usersettings();
                userSettings.uilanguageid = new CrmNumber(languageid);

                UpdateUserSettingsSystemUserRequest updateUserSettings = new UpdateUserSettingsSystemUserRequest();
                updateUserSettings.UserId = new Guid(entityId);
                updateUserSettings.Settings = userSettings;
                try
                {
                    webService.Execute(updateUserSettings);
                    if (!quiet)
                    {
                        Console.WriteLine("User with id = {0} updated with Language settings", entityId);
                    }
                }
                catch (System.Web.Services.Protocols.SoapException ex)
                {
                    string err = string.Format("{0}\r\n", ex.ToString());
                    err = err + string.Format("Soap Exception Detail: {0}\r\n", ex.Detail.InnerXml);
                    err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
                    FileWriter.Instance.WriteToFile(err);
                }
                catch (Exception ex)
                {
                    string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
                        Thread.CurrentThread.GetHashCode());
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
                    err = err + ex.ToString();
                    FileWriter.Instance.WriteToFile(err);
                }
            }
            // Update the newly created systemuser with custom attributes.
            XmlNodeList propertyList = instanceXML.DocumentElement.SelectNodes("//property");
            if (propertyList != null && propertyList.Count != 0)
            {
                DynamicEntity dynUser = new DynamicEntity();
                dynUser.Name = EntityName.systemuser.ToString();
//                KeyProperty systemuserid = new KeyProperty("systemuserid", new Key(new Guid(entityId)));
                dynUser.Properties = new Property[propertyList.Count + 1];
                for (int j = 0; j < propertyList.Count; j++)
                {
                    XmlNode child = propertyList[j];
                    switch (child.Attributes["type"].Value)
                    {
                        case "string":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateStringProperty(child.Attributes["name"].Value, child.Attributes["value"].Value);
                            break;
                        case "owner":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateOwnerProperty(child.Attributes["name"].Value, CrmTypes.CreateOwner(EntityName.systemuser.ToString(), new Guid(child.Attributes["value"].Value)));
                            break;
                        case "picklist":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreatePicklistProperty(child.Attributes["name"].Value, CrmTypes.CreatePicklist(int.Parse(child.Attributes["value"].Value)));
                            break;
                        case "money":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmMoneyProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmMoney(decimal.Parse(child.Attributes["value"].Value)));
                            break;
                        case "boolean":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmBooleanProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmBoolean(bool.Parse(child.Attributes["value"].Value)));
                            break;
                        case "decimal":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmDecimalProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmDecimal(decimal.Parse(child.Attributes["value"].Value)));
                            break;
                        case "datetime":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmDateTimeProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmDateTime(child.Attributes["value"].Value));
                            break;
                        case "float":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateCrmFloatProperty(child.Attributes["name"].Value, CrmTypes.CreateCrmFloat(float.Parse(child.Attributes["value"].Value)));
                            break;
                        case "lookup":
                            ((DynamicEntity)dynUser).Properties[j] = CrmTypes.CreateLookupProperty(child.Attributes["name"].Value, CrmTypes.CreateLookup(EntityName.account.ToString(), new Guid(child.Attributes["value"].Value)));
                            break;
                        default:
                            Console.WriteLine(child.Attributes["type"].Value + " is not implemented yet. Needs to be implemented to generate Property");
                            break;
                    }
                }

                dynUser.Properties[propertyList.Count] = CrmTypes.CreateKeyProperty("systemuserid", new Key(new Guid(entityId)));
                
                TargetUpdateDynamic tud = new TargetUpdateDynamic();
                tud.Entity = dynUser;
                UpdateRequest updateRequest = new UpdateRequest();
                updateRequest.Target = tud;
                try
                {
                    webService.Execute(updateRequest);
                    if (!quiet)
                    {
                        Console.WriteLine("User with id = {0} updated with dynamic Attributes", entityId);
                    }
                }
                catch (System.Web.Services.Protocols.SoapException ex)
                {
                    string err = string.Format("{0}\r\n", ex.ToString());
                    err = err + string.Format("Soap Exception Detail: {0}\r\n", ex.Detail.InnerXml);
                    err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
                    FileWriter.Instance.WriteToFile(err);
                }
                catch (Exception ex)
                {
                    string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
                        Thread.CurrentThread.GetHashCode());
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
                    err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
                    err = err + ex.ToString();
                    FileWriter.Instance.WriteToFile(err);
                }
            }
            
            role roleRet = null;
                    
            if (instanceXML.DocumentElement.SelectSingleNode("role") != null)
            {
                // Retrieve the Role with the given name for the particular Business Unit first
                Guid businessunitid = new Guid(instanceXML.DocumentElement.SelectSingleNode("businessunitid").InnerText);
                QueryExpression query1 = new QueryExpression();
                query1.EntityName = "role";
                ColumnSet columnSet = new ColumnSet();
   
                columnSet.Attributes = new string [] {"roleid"};
                query1.ColumnSet = columnSet;
                ConditionExpression[] ceArray = new ConditionExpression[2];
                ceArray[0] = new ConditionExpression();
                ceArray[0].AttributeName = "name";
                ceArray[0].Operator = ConditionOperator.Equal;
                ceArray[0].Values = new object[] { instanceXML.DocumentElement.SelectSingleNode("role").InnerText };

                ceArray[1] = new ConditionExpression();
                ceArray[1].AttributeName = "businessunitid";
                ceArray[1].Operator = ConditionOperator.Equal;
                ceArray[1].Values = new object[] { businessunitid };

                query1.Criteria = new FilterExpression();
                query1.Criteria.Conditions = ceArray;

                try
                {
                    BusinessEntityCollection results = webService.RetrieveMultiple(query1);
                    BusinessEntity[] rolesReturned = results.BusinessEntities;
                    roleRet = (role)rolesReturned[0];
                }
                catch (System.Web.Services.Protocols.SoapException ex)
                {
                    FileWriter.Instance.WriteToFile(string.Format("{0}\r\nSoap Exception Detail: {1}", ex.ToString(), ex.Detail.InnerXml));
                }

                if (roleRet != null)
                {
                    AssignUserRolesRoleRequest assignRole = new AssignUserRolesRoleRequest();
                    assignRole.RoleIds = new Guid[1];
                    assignRole.RoleIds[0] = roleRet.roleid.Value;
                    assignRole.UserId = new Guid(entityId);

                    try
                    {
                        webService.Execute(assignRole);
                        if (!quiet)
                        {
                            Console.WriteLine("User with id = {0} assigned roleid = {1}", entityId, roleRet.roleid.Value.ToString());
                        }
                    }
                    catch (System.Web.Services.Protocols.SoapException ex)
                    {
                        string err = string.Format("{0}\r\n", ex.ToString());
                        err = err + string.Format("Soap Exception Detail: {0}\r\n", ex.Detail.InnerXml);
                        err = err + string.Format("XML : {0}\r\n", instanceXML.InnerXml);
                        FileWriter.Instance.WriteToFile(err);
                    }
                    catch (Exception ex)
                    {
                        string err = string.Format("[{0}]WARNING:  Unable to create crm entity.  Continuing, using null for child object's parentId\r\n",
                            Thread.CurrentThread.GetHashCode());
                        err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), instanceXML.InnerXml);
                        err = err + string.Format("[{0}]WARNING:  {1}\r\n", Thread.CurrentThread.GetHashCode(), ex.Message);
                        err = err + ex.ToString();
                        FileWriter.Instance.WriteToFile(err);
                    }
                }
                else
                {
                    string err = string.Format("No role could be found");
                    FileWriter.Instance.WriteToFile(err);
                }
            }
            
        }

		private static string m_entityXmlString =
			@"<systemuser>
    			<domainname></domainname>
				<firstname>replace(randomfirstname)</firstname>
				<lastname>replace(randomlastname)</lastname>
    			<businessunitid></businessunitid>
				<internalemailaddress>replace(randomemail)</internalemailaddress>
                <organizationid>replace(organizationidreplace)</organizationid>
    		</systemuser>";
	};

}
